How should response content type for documents be

2019-01-27 03:40发布

问题:

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)

回答1:

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.



回答2:

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).