How to Force Browser to Download File

How to force a Download File prompt instead of displaying it in-browser with HTML?

This is something that you cannot absolutely control with HTML itself.

If the user is having a browser with PDF reading capabilities (or a plugin) and the corresponding settings to open PDF files in-browser, the PDF will open like that.

The PDF opens in a new tab simple because of your target="_blank", which has nothing to do with a download prompt.

If you are using HTML5 you can use the download attribute:

<a href="sample.pdf" download="sample.pdf">Download</a>

If you have a back-end service which you can control or you feel like fiddling with your Web Server, you can always look for setting the right Content-Disposition. See this SO question for some nice discussion on Content-Disposition.

How to force browser to download file?

You are setting the response headers after writing the contents of the file to the output stream. This is quite late in the response lifecycle to be 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's outputstream.

Therefore, your method should be written as follows (this won't compile as it is a mere 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 failure is that it is possible for the actual headers sent by the servlet would be different from what you are intending to send. After all, if the servlet container does not know what headers (which appear before the body in the HTTP response), then it may set appropriate headers to ensure that the response is valid; setting the headers after the file has been written is therefore futile and redundant as the container might have already set the headers. You could confirm this by looking at the network traffic using Wireshark or a HTTP debugging proxy like Fiddler or WebScarab.

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

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

This method may be called repeatedly to change content type and character encoding. This method has no effect if called after the response has been committed.

...

Force browser download a large file

Ok, I have solved the problem. So if you send a file request yourself to the server from your javascript code the browser will just pass the received response directly to your response object, but you can't store it on the hard drive without some external (browser supported) tools.

What I mean is that if you perform any kind of $http.post() or .get() from your scripts the response will be passed to the $http.post().then(function(response){...}) directly and it's passed only after the whole response is received. Meaning that if you're expecting a file with the size of 5GB it will fail for being too large to be received inside the response object.

Instead what you have to do is to trigger the download in another way. What I did in my code is that I built a hidden

<form method="POST" action="/set.uri.here/" id="download">...</form>

and when the user clicks the button to download the file, I run a function that builds the body of the form and then submits it. Which looks like

var form = document.getElementById("download");
// magic here... create the body for the form and so on
form.submit();

This way you can pass the request to be done by your browser so that then the response will be also handled by the browser. This is the crucial difference between doing the request yourself or by the browser. If you do the request yourself then the browser won't download the object but you will receive it yourself to do something with it.

If you wish the browser to download the object, then, make the browser do the request for the object as well!

How to force browser to download, not view, PDF documents in ASP.NET Webforms

Use a linkbutton so you can run serverside code on click:

<asp:LinkButton ID="hl_download" runat="server" OnClick="hl_download_Click">Download</asp:LinkButton>

Then, in the codebehind:

public void hl_download_Click(Object sender, EventArgs e)
{
Response.AddHeader("Content-Type", "application/octet-stream");
Response.AddHeader("Content-Transfer-Encoding","Binary");
Response.AddHeader("Content-disposition", "attachment; filename=\"IdeaPark_ER_diagram.pdf\"");
Response.WriteFile(HttpRuntime.AppDomainAppPath + @"ideaPark\DesktopModules\ResourceModule\pdf_resources\IdeaPark_ER_diagram.pdf");
Response.End();
}

This assumes that the web path maps cleanly to the filesystem path of the file. Otherwise modify Response.WriteFile() so that it points to the location of the pdf file on the filesystem.



Related Topics



Leave a reply



Submit