Java webapp:添加内容处置标头以强制浏览器“另存为”行为

即使它不是HTTP 1.1 / RFC2616 webapps的一部分,希望强制在浏览器中下载 (而不是显示)资源,也可以使用Content-Disposition标头,如下所示:

 Content-Disposition: attachment; filename=FILENAME 

即使很难,它只在RFC2183中定义,而不是 HTTP 1.1的一部分,它可以在大多数Web浏览器中使用。

所以从客户端来看,一切都很好。

但是在服务器端,在我的情况下,我有一个Java webapp,我不知道我应该如何设置该头,特别是在以下情况下…

我将在Amazon S3实例上托管一个文件(称为“ bigfile ”)(我的S3存储桶可以使用部分地址访问,例如: files.mycompany.com/ ),这样用户就可以在文件中访问此文件.mycompany.com / bigfile

现在有没有办法制作一个servlet (或.jsp ),以便在用户想要下载该文件时始终添加Content-Disposition标头?

代码会是什么样的,如果有的话会有什么问题?

您不会有一个直接引用该文件的URL。 相反,您将拥有一个指向您的servlet代码的URL(或者您的服务器端框架中的某种操作代码)。 反过来,在设置标题后,它必须访问文件内容并将其铲出到客户端。 (您还需要记住在适当的时候处理缓存控制标头。)

HttpServletResponse类具有API,可以让您设置所需的所有标头。 您必须确保开始转储文件内容之前设置标头,因为标头必须首先在发送到浏览器的流中出现。

这与您可能拥有可以即时生成下载的servlet的情况没有太大区别。

编辑我会把这些东西留在这里为了后人的缘故,但我会注意到,当你存储一个文件时,有一些方法可以将一些HTTP标头移交给S3,这样亚马逊就会把它们吐出来何时提供文件。 我不确定你是怎么做到的,而且我不确定“Content-disposition”是一个你可以这样设置的标题,但我会继续寻找。

Pointy指出,我得到了这个工作。 现在可以链接到名为download.jsp的JSP,而不是直接链接到资产 – 在我的情况下是pdfs – 它接受并解析GET参数,然后将pdf作为下载提供。

在这里下载

这是我使用的jsp代码。 它在IE8,Chrome和Firefox中工作:

 <%@page session="false" contentType="text/html; charset=utf-8" import="java.io.IOException, java.io.InputStream, java.io.OutputStream, javax.servlet.ServletContext, javax.servlet.http.HttpServlet, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.io.File, java.io.FileInputStream" %> <% //Set the headers. response.setContentType("application/x-download"); response.setHeader("Content-Disposition", "attachment; filename=downloaded.pdf"); [pull the file path from the request parameters] File file = new File("[pdf path pulled from the requests parameters]"); FileInputStream fileIn = new FileInputStream(file); ServletOutputStream outstream = response.getOutputStream(); byte[] outputByte = new byte[40096]; while(fileIn.read(outputByte, 0, 40096) != -1) { outstream.write(outputByte, 0, 40096); } fileIn.close(); outstream.flush(); outstream.close(); %> 

.htaccess文件放在根文件夹中,并带有以下行:

 Header set Content-Disposition attachment 

我刚刚通过谷歌找到了这个。

我有一个类似的问题,但我仍然想使用Servlet(因为我生成内容)。


但是,在Servlet中只需要以下行。

 response.setHeader("Content-Disposition", "attachment; filename=downloadedData.json");