I have an Google App Engine (Java) based application which stores the file data in Google Cloud storage.
This file download servlet works fine in my local eclipse environment and when deployed to appspot domain, this works for simple text files but for any documents (displayed in the browser in a new tab), but if I try with any other binary files (doc, jpeg, gif etc) seem to do nothing, no error is thrown as well at the server side . I checked directly in the file folders in Google Cloud storage, files are stored properly and able to access it directly, but cannot do so via the app engine.
Can you please let me know if I am missing something?
The code snippet below,
try {
FileService newfileService = FileServiceFactory.getFileService();
AppEngineFile file = new AppEngineFile(cloudpath) ;
FileReadChannel channel = newfileService.openReadChannel(file, false);
BufferedInputStream bis = new BufferedInputStream(Channels.newInputStream(channel));
BufferedOutputStream bos = new BufferedOutputStream(resp.getOutputStream());
resp.setHeader("Content-Disposition", "inline;filename=\"" + file.getNamePart() + "");
int b = 0;
while((b = bis.read()) != -1) {
bos.write(b);
}
bos.flush();
} catch (Exception e) {
e.printStackTrace();
}
Instead of trying to stream the file yourself you should use the BlobstoreService.serve method. This takes care or streaming and can be used on files of any size.
Something like
BlobstoreService blobService = BlobstoreServiceFactory.getBlobstoreService();
blobService.serve(blobService.createGsBlobKey(cloudpath), resp);
you'll try the following order of statements.
...
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "inline;filename=\"" + file.getNamePart() + "");
BufferedOutputStream bos = new BufferedOutputStream(resp.getOutputStream());
int b=0;
...
Related
I have been trying to download files/whole directory from publicly available google drive link URL using Java. I am able to read files which are present in my google drive using google drive libraries but I am not able to understand how to pass google drive link URL.
Also, I tried to use typical method of downloading files from URL but it produced error java.io.IOException: Server returned HTTP response code: 400 for URL.
URL url;
URLConnection con;
DataInputStream dis;
FileOutputStream fos;
byte[] fileData;
try {
url = new URL("https://drive.google.com/drive/folders/<some-alphanumeric-code>/<file-name>"); //File Location goes here
con = url.openConnection(); // open the url connection.
dis = new DataInputStream(con.getInputStream());
fileData = new byte[con.getContentLength()];
for (int q = 0; q < fileData.length; q++) {
fileData[q] = dis.readByte();
}
dis.close(); // close the data input stream
fos = new FileOutputStream(new File("/Users/abhijeetkunwar/file.png")); //FILE Save Location goes here
fos.write(fileData); // write out the file we want to save.
fos.close(); // close the output stream writer
}
catch(Exception m) {
System.out.println(m);
}
Kindly suggest the solution please.
The link you are using contains the folder id, the folder should also be readable by everyone.
In this instance you can use the files.list method from the Google drive api and access it using 'folderid' in parents which will return a list of all of the files within that folder.
For this to work the folder needs to be public to viewers which yours seem to be, after our conversation in chat.
I have an XML file on Dropbox that I want to access from my Google App Engine using the Dropbox Java API. After a bit of playing around I find the GAE doesn't support FileOutputStream.
FileOutputStream outputStream = new FileOutputStream("myFile.txt");
try {
DbxEntry.File downloadedFile = client.getFile("/myFile.txt", null,
outputStream);
System.out.println("Metadata: " + downloadedFile.toString());
}
Any ideas how I can get the XML data into my GAE (client or server side) from Dropbox?
Thanks
Tim
Got it! Thanks. ByteArrayOutputStream worked. So for anyone else trying to read a DropBox file in a Google App Engine environment (i.e. read into memory), here is what worked for me
String fileName = "myfile.xml"; OutputStream out = new ByteArrayOutputStream();
try {
dbxClient.getFile("/" + fileName, null, out);
} catch (DbxException e) {
e.printStackTrace();
}
System.out.println("File Contente: " + out.toString());
Drive Quickstart: Run a Drive App in Java example works for uploading files fine. I want to download the files from Gdrive to local system by using java.
For download they are given a method
private static InputStream downloadFile(Drive service, File file) {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
HttpResponse resp =
service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl())).execute();
return resp.getContent();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
The above method,how can i give inputs? and from where i give the inputs? Can anyone give a complete code for download like Quickstart upload class.
any help will be appreciated.
you can use google drive api and send Http get request, you can see this tutorial
https://developers.google.com/drive/manage-downloads
Thanks Hanan it works fine.By using the retrieveAllFiles() i can list all the documents.And i have stored the retrieved documents in my local by using this below code.Is it a correct way to download.
for(File f:result){
i++;
System.out.println("File Name==>"+f.getTitle());
System.out.println("File Id==>"+f.getId());
System.out.println("File ext==>"+f.getFileExtension());
System.out.println("File size==>"+f.getFileSize());
InputStream in = downloadFile(service,f);
byte b[] = new byte[in.available()];
in.read(b);
java.io.File ff = new java.io.File("/home/test/Desktop/gdocs/"+f.getTitle());
FileOutputStream fout = new FileOutputStream(ff);
fout.write(b);
fout.close();
}
It stores all the documents in local. The text (.txt) files are open properly in my local, but the image files or pdf files are not open properly.It gives some error messages like file corrupted. There is no content in the image or pdf documents how can i get content and store it. Any suggestions
I am uploading a file with the PF 3.5 File Uploader
My Upload Method looks like that:
public void handleFileUpload(FileUploadEvent event) {
log.info("Method handleFileUpload invoked");
FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
InputStream inputStream = null;
OutputStream out = null;
try {
File targetFolder = new File("\\resources\\uploads");
if(!targetFolder.exists()) {
targetFolder.mkdirs();
}
inputStream = event.getFile().getInputstream();
File outFile = new File(targetFolder, event.getFile().getFileName());
log.info("copy file stream to " + outFile.getAbsolutePath());
out = new FileOutputStream(outFile);
int read = 0;
byte[] bytes = new byte[size];
log.info("read file stream");
while ((read = inputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
} catch (IOException e) {
log.error(e);
} finally {
...
}
at the moment my files get uploaded to \\resources\\uploads". Thats the path to a folder on theC:`.
However, I want to upload my uploads to a path in my eclipse project. How to change the path? I really appreciate your answer!!!
However, I want to upload my uploads to a path in my eclipse project.
That's absolutely not recommended for the reasons mentioned in this answer: Uploaded image only available after refreshing the page. The point is: the IDE's workspace and server's deploy folder is absolutely not intented as a permanent file storage. The uploaded files would be unreachable and/or disappear like by magic.
Just keep them in a path external to the IDE's workspace and server's deploy folder. You're doing it fine. I'd only make the path configurable by a system property, environment variable or properties file setting so that you don't need to edit, recompile, rebuild, etc the code everytime when you change the upload location.
If your concrete problem is more the serving of the uploaded file, then just add the upload folder as another context in server's configuration, or create a simple servlet for the serving job, or as you're using PrimeFaces, just use <p:fileDownload> or <p:graphicImage> with StreamedContent pointing to the desired FileInputStream.
See also:
How to save uploaded file in JSF
I have deployed an application in Google App Engine and and I want to upload and download data from server using java code at desktop and server code for download request and one more: Where do I store the data in apps engine?
To store binary data (file contents) you have three options:
Blob property of Datastore entities
Blobstore
Google Cloud Storage
You can save your file anywhere on your server, you just need to know the path.
how i direct it as output stream?
Here is a code snippet that can help you.
File fileOnServer = new File("Hello.txt"); // Give full path where your file is located
byte[] file = new byte[(int) fileOnServer.length()];
FileInputStream fileInputStream = new FileInputStream(fileOnServer);
fileInputStream.read(file);
int contentLength = (int) file.length;
response.setContentLength(contentLength);
response.setHeader("Content-Disposition", "attachment; filename=\"Hello.txt\"");
out = response.getOutputStream();
int bytesWritten = 0;
byte[] buffer = new byte[1024];
while (bytesWritten < contentLength) {
int bytes = Math.min(1024, contentLength - bytesWritten);
System.arraycopy(file, bytesWritten, buffer, 0, bytes);
if (bytes > 0) {
out.write(buffer, 0, bytes);
bytesWritten += bytes;
} else if (bytes < 0);
}
get download to user end?
Well you can add ClickHandler on a Button on your client side and override onClick method.
public void onClick(ClickEvent event) {
Window.open("UrlToYourServelet", "_blank", "null");
}
Hope this helps!
EDIT
I have found a solution. You can upload the file at any free file hosting site like this. This site provides a URL for every uploaded file. So in your servelet, make a HTTP request to the URL and download the file in byte[] and write it on outputStream as shown in the code above.