java generate dynamic csv file for download - java

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.

Related

how to append getRequestDispatcher with extra data in java?

So Basically I have:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/zips/packet.html").forward(request, response);
return;
}
As you can you can see when a request is made for this servlet, It responds with packet.html file. To be precise, inside my packet.html I have a video element with src="" which I need to fill it by users requested url.
Question: How do I send a little extra data saying video source to the client, So in my client side it could change the video source from src="" to src="actual video source"
I TRIED:
String video_source = "/zips/video.mp4";
response.getWriter().append(video_source);
request.getRequestDispatcher("/zips/packet.html").forward(request, response);
With this method I can see my packet.html being received in my front-end But I can't find the video_source. FYI: don't know how to receive the video_source.
Well, To satasify your demand you can follow many apporoaches. One approach that I would suggest would put into consideration whatever you've already started
As Below
Step 1. Forward your request and response objects into packet.jsp,instead of into packet.html
Step 2. inside packet.jsp grab the input from user and send it with
the request object from packet.jsp
Step 3. Write a servlet class that process the request object from
packet.jsp and send the video as mulitpart file with the response.
Moreover, Do some research on how to use jsp's and servlets
The second approach would be to write client side javascript code that send ajax request to grab the video in a second call. For this you might even consider some client side frameworks and libraries(like jquery, angular, etc) that ease your work.
You could do the following:
Pass that additional information via request attribute (request.setAttribute())
Use some dynamic handler (like a servlet or JSP) to serve /zips/handler.html
Use request.getAttribute() in that handler.
So:
in your initial servlet, put
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("real_source", /some real source/);
request.getRequestDispatcher("/zips/packet.html").forward(request, response);
return;
}
In your /zips/packet.html you just use request.getAttribute("real_source") to generate the html attribute you need.

A one step upload for uploading images using google app engine

I am trying to implement a very basic functionality of uploading images from Android,iPhone and web clients to the google app engine. I did an initial version of the implementation thanks to this blog:
However there always seems to be a 2 step process to uploading an image:
Get the initial upload URL to POST to using the createUploadUrl(). I am attaching the fragment of code which I use :
public class CreateUploadUrl extends HttpServlet {
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
String uploadURL = blobstoreService.createUploadUrl("/image/uploadImage");
resp.setContentType("text/plain");
resp.getWriter().println(uploadURL);
}
}
POST the image using the URL which you just "got"
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
BlobKey blobKey = ParameterExtractor.getBlobParameter(req, "blob-key", blobstoreService);
if (blobKey == null) {
log.info("blob Id is null. POST failed");
} else {
log.info("ze business logic");
}
}
My question is if it is possible to do it in one step since right now all clients need to do a http GET to get the upload URL and then a http POST to POST the image.
Is it not possible to just do one Http POST with a predefined URL.
Thanks
Rajat
This is possible, with limitations. You can bypass the UploadUrl mechanism by creating blobs directly in your servlet using the (currently experimental) createNewBlobFile API. In your mobile app(s) create an HTTP request encoded as multipart/form-data, and teach your servlet how to decode such a thing (consult e.g. How to upload files in JSP/Servlet?). Be aware that HTTP requests are limited to 32MB; with form encoding the amount of binary data you can upload will be less than that.
Sure you can do it with single POST. For example you have user that have an id. This user select image and you send in POST image data and user data on client side.
On server side (GAE) you have url for image uploding (your_host/imageUpload) and server or Spring controller that read data from request and write it to Blobstore.

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.

Handle attachment in response with RequestBuilder in GWT

I am making a HTTP POST request from GWT Client to a HTTPServlet. This Servlet is creating a PDF file from request content and writing it to response stream.
Headers of the response stream are:
Content-Disposition: attachment; filename=report.pdf
I want to open this PDF in new window of the user's browser or prompt him to download it.
import com.google.gwt.http.client.*;
...
String url = "http://www.myserver.com/getData?type=3";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
try {
Request request = builder.sendRequest(data, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Couldn't connect to server (could be timeout, SOP violation, etc.)
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
// Window.open(url, "_blank", "");
} else {
// Handle the error. Can get the status text from response.getStatusText()
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
How should I handle response in onResponseRecieved?
I think in this case you should not use a single RequestBuilder AJAX call. You can rely on the default browser behavior by invoking a normal call and letting the browser handle the PDF response (displaying it with a PDF viewer plugin or opening a Save dialog).
There are several alternatives to achieving this:
If you can pass your data in a GET request (only possible for a small data volume) you can create the URL with the data as GET parameters and then open a new browser window with Window.open() passing the URL with data.
For larger amounts of data you can first POST your data with RequestBuilder to the server to store the data temporaly and in RequestCallback.onResponseReceived() open a new browser window with a short URL like above in alternative 1. On the server side you have to split the PDF generation servlet into two parts: a data store servlet with POST method (i.e. storing the data into the web session) and a PDF render servlet with GET method, which takes the data out of the session (and deleting it) and doesn't need large parameters.
Create a form with method POST, hidden fields for your data and the PDF generation servlet URL. Fill the hidden fields with your data and submit the form programmatically (i.e. FormPanel.submit()). If you create your FormPanel with a target name the browser opens a new window or uses the specified frame to handle the response.
On the client side, use an Anchor instead of a request builder and invoke the servlet directly
by using Window.Location.replace(URL.encode(formActionUrl));

Help with file upload in Java/J2EE

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.

Categories