I have been struggling with this for a while and I could not find the answer for my problem.
The scenario is the following:
One web application using play framework lunched on Google app engine. Attempting to attach 2 pdf file to the email and send it. With one file it is working perfectly. With two I get errors.
Here is the code:
package app;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.MimeType;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
public class Mailer {
public static void sendEmail(String to, String subject, String body, byte[] pdf1, byte[] pdf2)
throws AddressException, MessagingException, UnsupportedEncodingException{
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("myAddress#gmail.com", "John Smith"));
msg.addRecipient(Message.RecipientType.TO, new InternetAddress(to, to));
msg.setSubject(subject);
msg.setText(body);
Multipart mp = new MimeMultipart();
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(body, "text/html");
mp.addBodyPart(htmlPart);
//Attaching first pdf
MimeBodyPart attachment = new MimeBodyPart();
attachment.setFileName("pdf1.pdf");
DataSource src = new ByteArrayDataSource(pdf1, "application/pdf");
attachment.setDataHandler(new DataHandler(src));
mp.addBodyPart(attachment);
//Attaching second pdf
attachment = new MimeBodyPart();
attachment.setFileName("pdf2.pdf");
src = new ByteArrayDataSource(badgePDF, "application/pdf");
attachment.setDataHandler(new DataHandler(src));
mp.addBodyPart(attachment);
msg.setContent(mp);
Transport.send(msg);
}
}
Unfortunately I have no error message even if I print the caught exception's stackTrack, but I my guess is that there is an issue with the DataSource object. I appreciate any kind of help.
You should use FileDataSource for your DataSource type instead of using ByteArrayDataSource. Try the following:
Multipart mp = new MimeMultipart();
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(body, "text/html");
mp.addBodyPart(htmlPart);
File[] attachments = new File[2];
atts[1] = new File("pdf1.pdf");
atts[2] = new File("pdf2.pdf");
for( int i = 0; i < attachments.length; i++ ) {
messageBodyPart = new MimeBodyPart();
FileDataSource fileDataSource =new FileDataSource(attachments[i]);
messageBodyPart.setDataHandler(new DataHandler(fileDataSource));
messageBodyPart.setFileName(attachments[i].getName());
mp.addBodyPart(messageBodyPart);
}
msg.setContent(mp);
Transport.send(msg);
Related
I am new in programming and seeking for a solution to my problem. Here, I am going to describe my problem in as much clarity as I can.
So, I am working on a problem where I have to create an API which is going to accept (String1, String2, Mediafile(mp3), Mediafile(txt)) and then I have to upload these files somewhere else.
Here, I want to know do we expect Media Files in the byte[] format or is there any way that I can get that Mediafile as it is(Not in Byte format).
package com.self.projects;
import java.io.IOException;
import org.springframework.boot.json.JsonParseException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
#RestController
#RequestMapping("/hellomedia")
public class TestMediafile {
#RequestMapping(value = "addDetails", method = RequestMethod.POST , consumes = "multipart/form-data")
public StudentClassReport addProduct(
#RequestParam String studentReportJson,
#RequestParam MultipartFile report,
#RequestParam MultipartFile transcription,
#RequestParam int marks) throws JsonParseException, JsonMappingException, IOException {
studentClassReport studentReport = new objectMapper().readValue(studentReportJson, StudentClassReport.class);
byte[] myReport = report.getBytes();
byte[] myTranscription = transcription.getBytes();
studentReport.setTranscription(myTranscription);
studentReport.setReport(myReport);
return studentReport;
}
}
I want to download a file in Selenium web driver in C#.
i have the url in the web element as the attribute href. With that url, i have to download the file through javascript executor.
I tried with js executescript to get the file in the form of bytes and then converting it to pdf file and storing in my desired location. But no luck
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.win-rar.com/predownload.html?&L=0");
string linkVal = driver.FindElement(By.LinkText("Download WinRAR")).GetAttribute("href");
var href = "https://www.win-rar.com/fileadmin/winrar-versions/winrar/winrar-x64-571.exe";
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
/// Object reposne = js.ExecuteScript("arguments[0].setAttribute(arguments[1],arguments[2])", linkVal, "href", "https://www.win-rar.com/postdownload.html?&L=0");
String script = "document.querySelector('a[href*=\"/print/\"]').setAttribute('download','name-of-the-download-file-recommend-guid-or-timestamp.pdf');";
///Object reposne = js.ExecuteAsyncScript(script , href);
var bytes = Convert.FromBase64String(reposne.ToString());
File.WriteAllBytes("F:\\file.exe", bytes);
I'm actually using RestSharp.
Like so:
public FileInfo DownloadFile(string downloadUrl)
{
RestClient rest = new RestClient();
RestRequest request = new RestRequest(downloadUrl);
byte[] downloadedfile = rest.DownloadData(request);
string tempFilePath = Path.GetTempFileName();
File.WriteAllBytes(tempFilePath, downloadedfile);
return new FileInfo(tempFilePath);
}
Consider not creating a rest client for each download request.
The RestClient also supports a base URL for convenience.
Hope this is what you wanted.
I have tested your scenario using Java, Selenium and TestNG. Where you can save the file in the root folder directory
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class FileDownload {
File folder;
WebDriver driver;
#SuppressWarnings("deprecation")
#BeforeMethod
public void setUp() {
//a random folder will be created 88998-98565-09792-783727-826233
folder = new File(UUID.randomUUID().toString());
folder.mkdir();
//Chrome Driver
System.setProperty("webdriver.chrome.driver", "---Your Chrome Driver or chromedriver.exe URL;--");
ChromeOptions options = new ChromeOptions();
Map<String, Object> prefs = new HashMap<String, Object>();
//When you click on download, it will ignore the popups
prefs.put("profile.default_content_settings.popups", 0);
prefs.put("download.default_directory", folder.getAbsolutePath());
options.setExperimentalOption("prefs", prefs);
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(cap);
}
#Test
public void downloadFileTest() throws InterruptedException{
driver.get("https://www.win-rar.com/predownload.html?&L=0");
driver.findElement(By.linkText("Download WinRAR")).click();
/* Depending on your download speed you have to increase or decrease the sleep value, if you give less than download time it will give error as: java.lang.AssertionError: expected [true] but found [false] */
Thread.sleep(5000);
File listOfFiles[] = folder.listFiles();
Assert.assertTrue(listOfFiles.length>0);
for(File file: listOfFiles){
Assert.assertTrue(file.length()>0);
}
}
#AfterMethod
public void tearDown() {
driver.quit();
/* You can comment below "for loop": for testing purpose where you can see the folder and file download, if you uncomment it will delete the file and folder: useful for regression you wont end up having so many files in the root folder */
for(File file: folder.listFiles()){
file.delete();
}
folder.delete();
}
}
If you are just trying to download the file, all you really need is this.
driver.FindElement(By.Id("download-button")).Click();
This will save it in your default location for your browser.
or in js executor
WebElement element = driver.findElement(By.id("download-button"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);
To go to a specific location, try adding chrome options:
in C#
ChromeOptions options = new ChromeOptions();
options.AddArguments("--disable-extensions");
options.AddArguments("disable-infobars");
options.AddUserProfilePreference("download.default_directory", "My Path");
options.AddUserProfilePreference("profile.password_manager_enabled", false);
options.AddUserProfilePreference("credentials_enable_service", false);
_Driver = new ChromeDriver(#"DriverPath"), options);
_wait = new WebDriverWait(_webDriver, TimeSpan.FromSeconds(10));
_Driver.Manage().Window.Maximize();
as a last resort, just move the file with:
public class MoveMyFile
{
static void Main()
{
string sourceFile = #"C:\My\File\Path\file.txt";
string destinationFile = #"C:\My\New\Path\file.txt";
// Move my file to a new home!
System.IO.File.Move(sourceFile, destinationFile);
}
}
Thankfully, Google announced the export logic from cloud Datastore. I would like to set up schedule-export in my platform. However, it's not Python, but Java. So I need to use cron.xml and Java logic to design this logic.
Is there any reference to design Datastore export logic (cloud_datastore_admin.py) in Java? Especially, I need to transform this part in Java
app = webapp2.WSGIApplication(
[
('/cloud-datastore-export', Export),
], debug=True)
https://cloud.google.com/datastore/docs/schedule-export
You can create the skeleton for App Egnine by following these instructions.
Once you have the skeleton, add something like this to handle export requests:
CloudDatastoreExport.java
package com.google.example.datastore;
import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
import com.google.apphosting.api.ApiProxy;
import com.google.common.io.CharStreams;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Logger;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
#WebServlet(name = "CloudDatastoreExport", value = "/cloud-datastore-export")
public class CloudDatastoreExport extends HttpServlet {
private static final Logger log = Logger.getLogger(CloudDatastoreExport.class.getName());
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// Verify outputURL parameter
String outputUrlPrefix = request.getParameter("output_url_prefix");
if (outputUrlPrefix == null || !outputUrlPrefix.matches("^gs://.*")) {
response.setStatus(HttpServletResponse.SC_CONFLICT);
response.setContentType("text/plain");
response.getWriter().println("Error: Must provide a valid output_url_prefix.");
} else {
// Get project ID
String projectId = ApiProxy.getCurrentEnvironment().getAppId();
// Remove partition information to get plain app ID
String appId = projectId.replaceFirst("(.*~)", "");
// Get access token
ArrayList<String> scopes = new ArrayList<String>();
scopes.add("https://www.googleapis.com/auth/datastore");
final AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
final AppIdentityService.GetAccessTokenResult accessToken =
appIdentity.getAccessToken(scopes);
// Read export parameters
// If output prefix does not end with slash, add a timestamp
if (!outputUrlPrefix.substring(outputUrlPrefix.length() - 1).contentEquals("/")) {
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
outputUrlPrefix = outputUrlPrefix + "/" + timeStamp + "/";
}
String[] namespaces = request.getParameterValues("namespace_id");
String[] kinds = request.getParameterValues("kind");
// Build export request
JSONObject exportRequest = new JSONObject();
exportRequest.put("output_url_prefix", outputUrlPrefix);
JSONObject entityFilter = new JSONObject();
if (kinds != null) {
JSONArray kindsJSON = new JSONArray(kinds);
entityFilter.put("kinds", kinds);
}
if (namespaces != null) {
JSONArray namespacesJSON = new JSONArray(namespaces);
entityFilter.put("namespaceIds", namespacesJSON);
}
exportRequest.put("entityFilter", entityFilter);
URL url = new URL("https://datastore.googleapis.com/v1/projects/" + appId + ":export");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
exportRequest.write(writer);
writer.close();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
JSONTokener exportResponseTokens = new JSONTokener(connection.getInputStream());
JSONObject exportResponse = new JSONObject(exportResponseTokens);
response.setContentType("text/plain");
response.getWriter().println("Export started:\n" + exportResponse.toString(4));
} else {
InputStream s = connection.getErrorStream();
InputStreamReader r = new InputStreamReader(s, StandardCharsets.UTF_8);
String errorMessage =
String.format(
"got error (%d) response %s from %s",
connection.getResponseCode(), CharStreams.toString(r), connection.toString());
log.warning(errorMessage);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("text/plain");
response.getWriter().println("Failed to initiate export.");
}
}
}
}
You can use the same cron.yaml from the docs:
cron:
- description: "Daily Cloud Datastore Export"
url: /cloud-datastore-export?namespace_id=&output_url_prefix=gs://BUCKET_NAME[/NAMESPACE_PATH]
target: cloud-datastore-admin
schedule: every 24 hours
Use gcloud to deploy the cron job:
gcloud app deploy cron.yaml
Make sure you complete this part to give GAE export and bucket permissions or else
you'll get permission denied errors:
https://cloud.google.com/datastore/docs/schedule-export#before_you_begin
The code snippet you showed is just a part of the typical GAE app skeleton specific for 1st generation standard environment python apps. You can easily recognize it in the main.py section of the python quickstart Hello World code review.
The code initializes the app variable (from the main python module, i.e. the main.py file) which is referenced in the app.yaml handler config as script: main.app.
The corresponding java app skeleton is significantly different, see the java quickstart Hello World code review. But no worries, you shouldn't need to specifically transform that code snippet, you just need to build your java app skeleton and focus on what the app handler actually does - making those POST requests to the datastore. Sorry I can't help more, but I'm not a java user.
What I really realized is that app.yaml is like Web.xml in java
and cloud-datastore-export is a servlet that communicates with gae to export data but I can't do more
API Calls,e.g. to Firebase https://fcm.googleapis.com/fcm/send worked before switching from <env>vm</env> appengine-web.xml to
env: flex app.yaml flexible.
When deploying with mvn appengine:deploy everything is fine, but when an API call gets fired, which worked before, i get the exception below:
Exception in thread "Thread-14" com.google.apphosting.api.ApiProxy$CallNotFoundException:
Can't make API call urlfetch.Fetch in a thread that is neither the original request thread nor a thread created by ThreadManager
at com.google.apphosting.api.ApiProxy$CallNotFoundException.foreignThread(ApiProxy.java:800)
at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:112)
at com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:40)
at com.google.api.client.extensions.appengine.http.UrlFetchRequest.execute(UrlFetchRequest.java:74)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
at com.qweez.flexenv.service.GameCounterService.run(GameCounterService.java:80)
it crashes when calling request.execute() below:
import com.google.api.client.http.ByteArrayContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
// stuff
try {
HttpRequest request = HttpRequestUtil.getHttpRequestFactory().buildPostRequest(new GenericUrl(GlobalConfig.MESSAGING_SERVER_URL), ByteArrayContent.fromString("application/json", requestBody));
HttpResponse response = request.execute();
//logger.warning(LOG_TAG+" ++++++ response status=" + response.getContent());
} catch (IOException e) {
logger.warning(LOG_TAG+" sent messge to topic error: " + e.getMessage());
}
the helper class httpRequestUtil looks like this
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import java.io.IOException;
public class HttpRequestUtil {
private static HttpTransport httpTransport;
private static HttpRequestFactory requestFactory;
static {
httpTransport = UrlFetchTransport.getDefaultInstance();
requestFactory = httpTransport.createRequestFactory(new HttpRequestInitializer() {
#Override
public void initialize(com.google.api.client.http.HttpRequest httpRequest) throws IOException {
HttpHeaders hh = new HttpHeaders();
hh.setAuthorization(GlobalConfig.SERVER_KEY);
hh.setContentType("application/json");
httpRequest.setHeaders(hh);
}
});
}
public static HttpRequestFactory getHttpRequestFactory(){
return requestFactory;
}
Is there something deprecated now?
Or what's the issue here now?
Any help very appreciated. Thanks!
I am trying to set up my project to use the Google Calendar API. So far I have downloaded the latest libraries and imported them. At the moment I am trying to follow the tutorial from the Google developers which is found here.
From what I found out according to this link draft10 has been deprecated and I am trying to use other classes
which do not belong to draft10.
The following are my current imports:
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.auth.oauth2.AuthorizationCodeTokenRequest;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.client.util.Lists;
import com.google.api.client.util.store.DataStoreFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.Calendar;
import com.google.api.services.calendar.model.CalendarList;
import com.google.api.services.calendar.model.CalendarListEntry;
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.EventDateTime;
import com.google.api.services.calendar.model.Events;
And the following is the method taken from the Google sample with some changes:
public void setUp() throws IOException {
httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
// The clientId and clientSecret can be found in Google Developers Console
String clientId = "YOUR_CLIENT_ID";
String clientSecret = "YOUR_CLIENT_SECRET";
// Or your redirect URL for web based applications.
String redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
ArrayList<String> scopes = new ArrayList<String>();
scopes.add("https://www.googleapis.com/auth/calendar");
// Step 1: Authorize -->
String authorizationUrl = new GoogleAuthorizationCodeRequestUrl(clientId, redirectUrl, scopes)
.build();
// Point or redirect your user to the authorizationUrl.
System.out.println("Go to the following link in your browser:");
System.out.println(authorizationUrl);
// Read the authorization code from the standard input stream.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("What is the authorization code?");
String code = in.readLine();
// End of Step 1 <--
// Step 2: Exchange -->
GoogleTokenResponse response = new GoogleAuthorizationCodeTokenRequest(httpTransport, jsonFactory,
clientId, clientSecret, code, redirectUrl).execute();
// End of Step 2 <--
GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(
response.accessToken, httpTransport, jsonFactory, clientId, clientSecret,
response.refreshToken);
Calendar service = new Calendar(httpTransport, accessProtectedResource, jsonFactory);
service.setApplicationName("YOUR_APPLICATION_NAME");
}
The only problem is with the GoogleAccessProtectedResource class. It is giving me the following error: GoogleAccessProtectedResource cannot be resolved to a type.
Does anyone have any ideas on how I can get around this?
I managed to figure this out. All I had to do was to import the following packages:
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.plus.Plus;
import com.google.api.services.plus.PlusScopes;
And replace the following code:
GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(
response.accessToken, httpTransport, jsonFactory, clientId, clientSecret,
response.refreshToken);
Calendar service = new Calendar(httpTransport, accessProtectedResource, jsonFactory);
service.setApplicationName("YOUR_APPLICATION_NAME");
With this code:
GoogleCredential credential;
credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory).setServiceAccountId("[[INSERT SERVICE ACCOUNT EMAIL HERE]]")
.setServiceAccountScopes(Collections.singleton(PlusScopes.PLUS_ME))
.setServiceAccountPrivateKeyFromP12File(new File("key.p12"))
.build();
Plus plus = new Plus.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("YOUR_APPLICATION_NAME")
.build();