GWT: Get URL of file located on server - file

I am developing an web application which can upload/download a file from client to PostgreSQL database server via GWT RPC call.
I managed to create an upload servlet which store desired file(choosed by user via FileUpload widget) to Glassfish "TEMP" directory => then i used SQL command:
INSERT INTO table VALUES ('"+name+"',lo_import('"+f.getCanonicalPath()+"\\TEMP\\"+name+"'),...)
which put that file into database. This works pretty good.
Problem occurs when i want to download file from server to client. First i need to put the file back to TEMP dir with SQL command lo_export(...) -> this didn't work (some ERROR when creating a server file, permission denied), so i put the file manually to TEMP dir.
Question is how can i display that file which is stored on server in TEMP dir?
my path to glassfish server temp dir:C:\Program Files (x86)\glassfish-3.1\glassfish\domains\domain1\TEMP\example.pdf
when deploying app url looks like: http://localhost:8080/AppName/
i tried something like that: Window.open("http://localhost:8080/AppName/TEMP/example.pdf", "_blank", "enabled")
My CODE:
Client side:
String link = GWT.getModuleBaseURL() + "filedownloadservlet";
Window.open(link,event.getSelectedItem().getText(),"enabled");
so i pass to servlet located on server side a link and a file name...am i right ?
Server side:
public class FileDownloadServlet extends HttpServlet {
private String path = "TEMP//"; // Your absolute path
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String filename = req.getParameter("filename");
System.out.println(filename); // THIS IS NULL value
File userManualFile = new File(path + filename);
// You can fetch a Blob from the database instead.
ServletOutputStream servletOutputStream = resp.getOutputStream();
resp.setContentType("application/pdf");
resp.addHeader("content-disposition", "attachment; filename=skuska.pdf");
FileInputStream fileInputStream = new FileInputStream(userManualFile);
IOUtils.copy(fileInputStream, servletOutputStream);
servletOutputStream.flush();
When i press a file in Tree widget it shows me a new browser window with this error:
java.io.FileNotFoundException: TEMP\null (The system cannot find the file specified)

You cannot download a file with a RPC call. You must use a normal java servlet. You have to write the bytes into the HttpServletResponse. You can get the bytes from the file in the database by doing an SQL query.
This example is done with spring MVC.
#Controller
public class UserManualServlet {
private String path = "..." // Your absolute path
#RequestMapping("/app/usermanual.download")
public void generateInterceptActivationDeactivationReport(HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String filename = request.getParameter("filename");
File userManualFile = new File(path + filename);
// You can fetch a Blob from the database instead.
ServletOutputStream servletOutputStream = response.getOutputStream();
response.setContentType("application/pdf");
response.addHeader("content-disposition", "attachment; filename=\"user-manual.pdf\"");
FileInputStream fileInputStream = new FileInputStream(userManualFile);
IOUtils.copy(fileInputStream, servletOutputStream);
servletOutputStream.flush();
}
In this example, you can call the URL : ../app/usermanual.download?filename=usermanual.pdf to download the file.

Related

How to upload pdf files in Tomcat directory?

I am using Jersey for my REST backend, and i am developing a pdf upload feature. I prepared HTML form and backend REST method to upload, but i am able to upload only in my PC drive (example, on path C:/uploaded). Is there a method to upload in a Tomcat directory outside my app? For example, under "webapps/my-files"?
I am using Jersey 2.3 with multipart library and Tomcat 8.5.37 if needed.
I read lots of toturials and other questions, but all of then use c:/uploadedFiles or similar as upload location, so my doubts are still there.
First place, I wrote my REST service:
#POST
#Path("upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public String uploadFile (#FormDataParam("file") InputStream file, #FormDataParam("file") FormDataContentDisposition fileData) {
String uploadPath = "C:\\uploaded" + fileData.getFileName();
try {
int read = 0;
byte[] bytes = new byte[1024];
OutputStream out = new FileOutputStream(new File (uploadPath));
while ((read = file.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
return "Completed";
} catch (IOException ex) {
return ex.getMessage();
}
}
Then, i tried to call it from Postman with POST method and using a simple pdf file as request body, and it works.
But now I want to upload in a server folder and not in any C:/ drive location. I want to know, where should I put the directory on server? I tried under webapps/, is ok? And then, how can I set variable "uploadPath" correctly to upload in that directory?

how to download an attachment in browser?

I'm using the Gmail API in browser and want to allow the user to download email attachments. I see https://developers.google.com/gmail/api/v1/reference/users/messages/attachments/get but it returns JSON and base64 data. I don't think I can get that data in memory then trigger a "download" to save the file locally. Even if I could I don't think it would be efficient - it would probably download the file in memory vs. streaming it to a file. I think I need a direct link to a file that returns the correct file name and raw binary data (not base64). Is there a way to do this? Right now the only way I see is to proxy requests.
You can get the data from the base64 and save it to file locally.
If you are getting the attachment in Java, you can use the FileOutputStream class (or f.write() in Python) to write the bytes to file and save it locally with a path.
You can try with the following sample code from Google Developer page:
public static void getAttachments(Gmail service, String userId, String messageId)
throws IOException {
Message message = service.users().messages().get(userId, messageId).execute();
List<MessagePart> parts = message.getPayload().getParts();
for (MessagePart part : parts) {
if (part.getFilename() != null && part.getFilename().length() > 0) {
String filename = part.getFilename();
String attId = part.getBody().getAttachmentId();
MessagePartBody attachPart = service.users().messages().attachment().
get(userId, messageId, attId).execute();
byte[] fileByteArray = Base64.decodeBase64(attachPart.getData());
FileOutputStream fileOutFile =
new FileOutputStream("directory_to_store_attachments" + filename);
fileOutFile.write(fileByteArray);
fileOutFile.close();
}
}
}

ADF: How to get path of file when using InputFile Component

I am using jdeveloper version 11.1.1.5.0. In my use case I have created Mail Client Send Mail program where I used ADF InputFile component to attach File on mail.
But problem is that InputFile Component only return path of file(only get file name). And in my mail program DataSource class use full path to access file name.
UploadedFile uploadfile=(UploadedFile) actionEvent.getNewValue();
String fname= uploadfile.getFilename();//this line only get file name.
So how can I get full path using adf InputFile component or any other way to fulfill my requirement.
You could save the uploaded file in a path at the server. Only take care about naming that file, because of concurrency of users you should follow a policy about it, for example, adding te time in milliseconds to the name of the file. Like this...
private String writeToFile(UploadedFile file) {
ServletContext servletCtx =
(ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext();
String fileDirPath = servletCtx.getRealPath("/files/tmp");
String fileName = getTimeInMilis()+file.getFilename();
try {
InputStream is = file.getInputStream();
OutputStream os =
new FileOutputStream(fileDirPath + "/"+fileName);
int readData;
while ((readData = is.read()) != -1) {
os.write(readData);
}
is.close();
os.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return fileName;
}
This method also returns the new name of the uploaded file. You can replace getTimeInMilis() with any naming policy you like.
It would be a security issue if a web app is able to see anything other than the data stream for an uploaded file. The directory structure of the client would not be exposed to the webapp. As such, unless you plan to upload the file from the same host as the server, you will not have access to the file path on the client.
Note: Using answer instead of comment due to reputation threshold

Converting com.google.api.services.drive.model.File to java.io.File

So I want to create a java.io.File so that I can use it to generate a multipart-form POST request. I have the file in the form of a com.google.api.services.drive.model.File so I'm wondering, is there a way I can convert this Google File to a Java File? This is a web-app that uses the Google App Engine SDK, which prohibits every approach I've tried to make this work
No, you it doesn't seem like you can convert from com.google.api.services.drive.model.File to java.io.File. But it should still be possible to generate a multipart-form POST request using your data in Drive.
So the com.google.api.services.drive.model.File class is used for storing metadata about the file. It's not storing the file contents.
If you want to read the contents of your file into memory, this code snippet from the Drive documentation shows how to do it. Once the file is in memory, you can do whatever you want with it.
/**
* Download the content of the given file.
*
* #param service Drive service to use for downloading.
* #param file File metadata object whose content to download.
* #return String representation of file content. String is returned here
* because this app is setup for text/plain files.
* #throws IOException Thrown if the request fails for whatever reason.
*/
private String downloadFileContent(Drive service, File file)
throws IOException {
GenericUrl url = new GenericUrl(file.getDownloadUrl());
HttpResponse response = service.getRequestFactory().buildGetRequest(url)
.execute();
try {
return new Scanner(response.getContent()).useDelimiter("\\A").next();
} catch (java.util.NoSuchElementException e) {
return "";
}
}
https://developers.google.com/drive/examples/java
This post might be helpful for making your multi-part POST request from Google AppEngine.
In GoogleDrive Api v3 you can download the file content into your OutputStream. You need for that the file id, which you can get from your com.google.api.services.drive.model.File:
String fileId = "yourFileId";
OutputStream outputStream = new ByteArrayOutputStream();
driveService.files().get(fileId).executeMediaAndDownloadTo(outputStream);

File Upload google app engine blobstore

I am going to use Google app engine Blobstore to store my uploaded files. File type can be anything (.txt,.pdf,.docx etc)
I have written following servlet to download stored files in Google app engine Blobstore.
public class Serve extends HttpServlet {
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
blobstoreService.serve(blobKey, res);
}
}
But every time I request a file by giving a url as below,
http://127.0.0.1:8888/serve?blob-key=DEHQ3U_2wtUdEL7XPI434Q
file is downloaded nicely. But no extension for file. And name of the file is always ‘serve’
What should I do to download the uploaded file with the original name of the file?
Thanks,
I used the following code to serve a blob by passing the blob-key as a String to my Serve.java . File is downloaded using the original filename as well as the original extension. Found a more detailed discussion at http://onjava.com/onjava/excerpt/jebp_3/index3.html
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
BlobInfoFactory bi = new BlobInfoFactory();
BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
String fname = bi.loadBlobInfo(blobKey).getFilename();
res.setContentType("application/x-download");
res.setHeader("Content-Disposition", "attachment; filename=" + fname);
blobstoreService.serve(blobKey, res);
I know python has a send_as option that automatically sets the filename for the response, but I think in Java you will have to add a Content-Disposition header to the response like:
Content-Disposition: attachment; filename=your-file.docx;
The BlobInfo for your blob keeps the original filename and you can fetch it via getFilename

Resources