Help with file upload in Java/J2EE - java

I need to upload a file using Apache fileupload with ProgressListener but alongwith that I also need to show the progressbar for the upload status.
Actual requirement is I just need to parse a local XML file parse the xml into appropriate objects and put them in Database. Do I really need to upload the file to server to get it parsed. As I am getting exception like file not found on remote server while it runs fine on my local m/c.
Any quick help would be appreciated.
Thanks in advance !!!

If you have access to the server side, I advise to debug the upload process. The exception suggests that you want to open the file on the server based on the uploaded file name. On your local machine this works, because it runs on the same file system. On the server side, the Apache FileUpload receives binary data, which needs to be extracted from the request data stream:
#Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (ServletFileUpload.isMultipartContent(request)) {
FileItemFactory factory = new DiskFileItemFactory(Integer.MAX_VALUE, null);
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request);
for (FileItem item : items) {
byte[] data = item.get();
// do something with the binary data
}
} else {
System.err.println("Not a multipart/form-data");
}
}
And also you need the form to be:
<form name='frm' method="POST" action='UploadServlet'
id="frm" enctype="multipart/form-data">

From your description it sounds like your servlet is trying to read the file from the filesystem itself, based on the filename submitted in the form. This isn't going to work if the servlet is running on a different machine to where the file is.
Make sure your servlet is getting the file contents from the fileupload API, not from the local filesystem.

Related

How can i read a file in a ftp server using a servlet and then send this as a downloadable file to the user?

I have developed a servlet that offers some services.
I am using apache-commons-net FTPClient to log into a ftp server and read a file.
I want to make this file downloadle (aka send it to the outputstream maybe?) , but the only ways of reading a file that i know of are:
FTPClient.retrieveFileStream(String remote) and FTPClient.retrieveFile(String remote, OutputStream local).
I tried the first one and then wrote the InputStream i got to the outputStream of the servlet:
InputStream myFileStream = FTPClient.retrieveFileStream(fileName);
byte[] buffer = new byte[4096];
int length;
resp.reset();
resp.setContentType("text/csv");
resp.setHeader("Content-disposition","attachment; filename=\""+fileName+"\"");
OutputStream out = resp.getOutputStream();
while((length=myFileStream.read(buffer)) > 0){
out.write(buffer, 0, length);
}
myFileStream.close();
out.flush();
The Second One:
myClient.retrieveFile(fileName, resp.getOutputStream());
In both cases i get the text content of the file as a response and not the file itself.
Is there any way i can do this.
P.s. this code belongs to a medhod that is being called by the doPost() with http req and http resp as parameters.
If you want to download the file instead of just showing it, you have to change the content type you're sending to the browser (because it's browser's business to either display the data or save them as a file). Thus, do e.g.
resp.setContentType("application/octet-stream");
(instead of text/csv) to "hide" the real nature of the data from the browser and force it to save the data.
The problem was that i was using a google extension (DHC) to test my web service. and it displayed the file content instead of initializing the download.
I was making the file download in a doPost() method.
Solution:
I made it in a doGet() method and when accessed directly via browser everything works ok.
So i think it was only the extensions problem, which wrote the content of the response back to me instead of downloading the file attachment.
Thanks for the feedback to #Jozef

Jersey servlet returns zip file that contains more bytes than response sent

I'm trying to implement a simple servlet that returns a zip file that is bundled inside the application (simple resource)
So I've implemented the following method in the server side:
#GET
#Path("{path}/{zipfile}")
#Produces("application/zip")
public Response getZipFile(
#PathParam("path") String pathFolder,
#PathParam("zipfile") String zipFile) IOException {
String fullPath= String.format("/WEB-INF/repository/%s/%s",
pathFolder, zipFile);
String realPath = ServletContextHolder.INSTANCE.getServletContext()
.getRealPath(fullPath);
File file = new File(realPath );
ResponseBuilder response = Response.ok((Object) file);
return response.build();
}
When I call this method from the borwser, the zip file is downloaded and its size is the same number of bytes as the original zip in the server.
However, when I call this using a simple XMLHttpRequest from my client side code:
var oXHR = new XMLHttpRequest();
var sUrl = "http://localhost:8080/path/file.zip"
oXHR.open('GET', sUrl);
oXHR.responseType = 'application/zip';
oXHR.send();
I can see in the Network tab of the Developer tools in chrome that the content size is bigger, and I'm unable to process this zip file (for instance JSzip doesn't recognize it).
It seems like somewhere between my response and the final response from org.glassfish.jersey.servlet.ServletContainer, some extra bytes are written/ some encoding is done on the file.
Can you please assist?
Best Regards,
Maxim
When you use an ajax request, the browser expects text (by default) and will try to decode it from UTF-8 (corrupting your data).
Try with oXHR.responseType = "arraybuffer"; : that way, the browser won't change the data and give you the raw content (which will be in oXHR.response).
This solution won't work in IE 6-9 : if you need to support it, check JSZip documentation : http://stuk.github.io/jszip/documentation/howto/read_zip.html
If it's not the right solution, try downloading directly the zip file (without any js code involved) to check if the issue comes from the js side or from the java side.

Servlet Upload FIle via Post

I am working on an application that uses HTTP requests to send data from one server to another. Everything work just fine for strings, but I don't know how to send a file (file upload from one server to another).
I've looked over some examples, but I also need to be able to send a string (a file ID) along with the file.
The request is send from a Java class in the POST Method of that class. Is is like this: Client sends upload request for a file with an ID to a storage server. That storage server then uploads that file to another storage server...so the POST request from the first server to the other is send from the POST method method of that server.
Any sample code or link in the right direction are greatly appreciated.
Found this tutorial of how you can send the multi-part data using HttpClient. Take a look
The Commons FileUpload package makes it easy to add robust, high-performance, file upload capability to your servlets and web applications.
FileUpload parses HTTP requests which conform to RFC 1867, "Form-based File Upload in HTML". That is, if an HTTP request is submitted using the POST method, and with a content type of "multipart/form-data", then FileUpload can parse that request, and make the results available in a manner easily used by the caller, mentioned here.
See this
link can help you more.
Since you said -
"I also need to be able to send a string (a file ID) along with the
file"
You will have to parse the Http request and check if the FileItem is a form field (string/text - file ID in your case)
and process it accordingly.
Here is the sample code for multipart content requests -
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
FileItemFactory factory = new DiskFileItemFactory();
FileItem item=null;
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
servletFileUpload.setSizeMax(-1);
List items =null;
if (isMultipart) {
try
{
items = servletFileUpload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
item = (FileItem) iter.next();
if (item.isFormField())
{
//get your file Id from element to match with item.getFieldName() and do whatever you want
}
else if ( !item.isFormField() ){
//save your file here
}
Hope that helps you.
Here is the solution I managed to implement and it works: http://www.dreamincode.net/forums/topic/316513-upload-file-from-one-servlet-to-another/

Filter for limiting the file size on upload in Jersey

I have a HTML form that will upload a file (among other form fields) to my server. There, I am using Java and Jersey, and have created a filter which will throw an Exception if the file is to large (>10MB). But I can't seem to get the browser to stop the file upload as soon as I throw the exception. I can see that the reading from the InputStream stops after 10MB at the server side, but the browser will still continue to upload the file until it is finished. Only then will the error be shown.
Is there something with the way HTTP and browsers work that prevents this from working?
The user experience becomes worse if the user have to wait for the while file to be uploaded before getting the error.
This is the Jersey-filter I am using. This seems to be functioning correctly on the server side, so the problem seems to be with the browser.
import java.io.IOException;
import org.apache.commons.fileupload.util.LimitedInputStream;
import org.springframework.stereotype.Component;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;
import com.sun.jersey.spi.container.ContainerResponseFilter;
import com.sun.jersey.spi.container.ResourceFilter;
#Component
public class SizeLimitFilter implements ResourceFilter, ContainerRequestFilter {
#Override
public ContainerRequest filter(final ContainerRequest request) {
LimitedInputStream limitedInputStream = new LimitedInputStream(request.getEntityInputStream(), 1024 * 1024 * 10) {
#Override
protected void raiseError(final long pSizeMax, final long pCount) throws IOException {
// Throw error here :)
}
};
request.setEntityInputStream(limitedInputStream);
return request;
}
#Override
public ContainerRequestFilter getRequestFilter() {
return this;
}
#Override
public ContainerResponseFilter getResponseFilter() {
return null;
}
}
(and yes, I know there exists more sexy and modern solutions for uploading files (Javascript functions), but I need to use an approach that works in IE7 :/ )
Edit:
To clarify: everything works, the only problem is that I can't get the browser to show the error before the whole file is uploaded. Hence if I try to upload a 200MB file, the error won't be shown before the whole file is uploaded, even though my code throws an error just after 10MB...
This is because the browser doesn't look for a server response until AFTER it has sent the complete request.
Here are two ways to stop large file uploads before they arrive at your server:
1) Client-side scripting. An applet (Java file upload) or browser plug-in (Flash file upload, ActiveX, or whatever) can check the size of the file and compare it to what you declare to be the limit (you can use the OPTIONS request for this or just include the maximum size allowed in your form as either a hidden input or non-standard attribute on the file input element).
2) Use a 3rd party data service such as Amazon S3 that allows uploads directly from the browser. Set up the form on the page so that it uploads to the data service, and on success invoke some javascript function you write that notifies your server about an available file upload (with the instance details). Your server then sends a request to the data service to find out the size of the file... if it's small enough you retrieve it from the server side. If it's too large you just send a delete request to the data service and then send your response to the browser (your javascript function) that the file was too large and they need to do it again. Your javascript function then affects the display to notify the user.

java generate dynamic csv file for download

I have written a servlet that will return a csv file (dynamically generated) to the user to download. However the client is not able to see the file size which means they receive no progress indicator.
I have this code
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
try {
String csv = getCsv();
resp.setContentType("text/csv");
resp.setContentLength(csv.getBytes().length);
resp.getWriter().write(csv);
} catch (Exception e) {
log.error("error generating feed", e);
}
}
thank you.
Filesize is sent in a Response Header, specifically the Content-Length header. You have to build the entire response either in memory or on disk and calculate its size and send the Content-Length header with this size for the client to know how to calculate a progress indicator. You also with some non-standard browsers ( IE ) have to set the Disposition of the file to get the Download file dialog box to pop up and process the response correctly with a progress indicator.
Try using a browser like Firefox and the 'Live HTTP Headers' extension and 'Firebug' to debug what is actually being sent back.
You don't say what browsers this isn't working in so it may be browsers specific and need additional browsers specific meta-data.

Categories