How to make the browser download a file?

Everything works fine, but only if the file is small, about 1 MB, when I tried it with large files, for example, 20 MB, my browser displayed it, and not by force to download, I tried a lot of headers so far, now my code looks :

PrintWriter out = response.getWriter(); String fileName = request.getParameter("filename"); File f= new File(fileName); InputStream in = new FileInputStream(f); BufferedInputStream bin = new BufferedInputStream(in); DataInputStream din = new DataInputStream(bin); while(din.available() > 0){ out.print(din.readLine()); out.print("\n"); } response.setContentType("application/force-download"); response.setContentLength((int)f.length()); response.setHeader("Content-Transfer-Encoding", "binary"); response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName); in.close(); bin.close(); din.close(); 
+48
java java-ee servlets
Jun 29 '11 at 11:55
source share
3 answers

You adjust the response headers after writing the contents of the file to the output stream. It's pretty late in the response lifecycle for setting headers. The correct sequence of operations should be to set the headers first and then write the contents of the file to the servlet output stream.

Therefore, your method should be written as follows (this will not compile, as this is a simple representation):

 response.setContentType("application/force-download"); response.setContentLength((int)f.length()); //response.setContentLength(-1); response.setHeader("Content-Transfer-Encoding", "binary"); response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName); ... ... File f= new File(fileName); InputStream in = new FileInputStream(f); BufferedInputStream bin = new BufferedInputStream(in); DataInputStream din = new DataInputStream(bin); while(din.available() > 0){ out.print(din.readLine()); out.print("\n"); } 

The reason for the refusal is that the actual headers sent by the servlet may differ from what you intend to send. After all, if the servlet container does not know what headers (which appear before the body in the HTTP response), then it can set the appropriate headers to ensure that the response is valid; setting headers after the file has been written, so it’s useless and redundant because the container may already have set headers. You can confirm this by viewing network traffic using Wireshark or an HTTP debugging proxy such as Fiddler or WebScarab.

You can also refer to the Java EE API documentation for ServletResponse.setContentType to understand this behavior:

Sets the content type of the response sent to the client , if the response has not yet been committed. This type of content may include a character encoding specification, for example text / html; encoding = UTF-8. The response character encoding is only set from the specified content type if this method is called before getWriter is called.

This method can be called repeatedly to change the content type and character encoding. This method does not work if called after the response has been fixed.

...

+64
Jun 29 '11 at 12:05
source share
β€” -

Set the content type and other headers before you write the file. For small files, the contents are buffered, and the browser first receives the headers. For big data, the first data.

+4
Jun 29 '11 at 12:06 on
source share

This is from a php script that solves the problem perfectly with every browser I tested (FF with 3.5, IE8 +, Chrome)

 header("Content-Disposition: attachment; filename=\"".$fname_local."\""); header("Content-Type: application/force-download"); header("Content-Transfer-Encoding: binary"); header("Content-Length: ".filesize($fname)); 

So, as far as I can see, you are doing everything right. Have you checked your browser settings?

+3
Jun 29 '11 at 12:02
source share



All Articles