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
Java Linkedhashmap Get First or Last Entry
Preserving Parameter/Argument Names in Compiled Java Classes
Spring: Why Do We Autowire the Interface and Not the Implemented Class
Should I Use String.Isempty() or "".Equals(String)
Reversing a String with Recursion in Java
Understanding Strange Java Hash Function
Sending Email via Gmail Smtp Server in Java
Choosing the Best Concurrency List in Java
How to Find All the Methods That Call a Given Method in Java
Replace All Occurrences of a String Using Stringbuilder
Get Rid of "The Value for Annotation Attribute Must Be a Constant Expression" Message
Why Converting from Float to Double Changes the Value
A For-Loop to Iterate Over an Enum in Java
Generic Return Type Upper Bound - Interface VS. Class - Surprisingly Valid Code