I'm developing a simple servlet that should serve documents via http. I use URLs in the form of /getDocument?fileId=1234. The servlet simply 1) sets response.contentType and 2) writes to response.outputStream.
The problem is about setting the content type correctly in order to have the browsers understand the response (i.e., display the document using the correct application). Specifically:
a) For PDF files, if I set content type to "application/pdf", Internet Explorer understands (displays the document immediately) but Firefox does not (displays blank page without attempting to open any pdf viewer plugin). If I set it to "application/x-octetstream", Firefox understands it (displays it properly), but Internet Explorer says "unknown file type" when it asks me to save or open it.
b) Firefox understands "application/msword" and "application/vnd.ms-excel", but Internet Explorer does, strangely, not, it simple says "unknown file type".
Is it possible to get this to work consistently in all browsers, and if so, what is the correct way of setting content type for various document types? Is there anything else that should be set in the response in order for this do work correctly? Or, as I suspect, are the browsers getting confused when the URL does not end with the corresponding filename extension? (i.e., getFile?fileId=1234 instead of e.g. getFile/test.pdf)
Inside a servlet, the response content type ought to be set as follows:
response.setContentType(getServletContext().getMimeType(filenameWithExtension));
The ServletContext#getMimeType()
lookups all <mime-mapping>
entries in web.xml
for the content types associated with certain file extensions. You can find all default mappings in the appserver's own web.xml
(which in case of e.g. Tomcat is located in /conf/web.xml
). It might lack the "new" MSOffice OpenXML file extensions like xlsx
, docx
and so on. You can add them to your webapp's web.xml
like follows:
<mime-mapping>
<extension>xlsx</extension>
<mime-type>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</mime-type>
</mime-mapping>
As to how browsers handle the content type and the associated application, the major problem here is MSIE. It ignores the Content-Type
header and the filename
parameter of the Content-Disposition
header. It instead smartass-ingly guesses the content type based on the file extension in the URL and uses the last pathinfo of the URL as filename. As you've used a request parameter like /getDocument?fileId=1234
instead of a fullworthy filename+extension, the filename will become getDocument
and MSIE can't reliability "guess" the mime type of it. You should really include the filename+extension in the URL like /getDocument/filename.ext
. You can grab that part in the Servlet
by request.getPathInfo()
. For more servlet hints also see this article.
As to the problem of your Firefox not handling PDF files correctly, this must be a misconfiguration in your Firefox. Try verifying if everything looks right in Tools > Options > Applications. It is namely supposed to respect the aforementioned headers in a correct manner. You should only ensure that any Content-Length
header is correctly(!!) specified, else the file cannot be opened.
I'd recommend checking on a second machine, and also make sure that you have properly installed Acrobat Reader (in Mozilla, "about:plugins" gets you to the plugin registry).