public void download() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
ec.setResponseContentType(contentType); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ExternalContext#getMimeType() for auto-detection based on filename.
ec.setResponseContentLength(contentLength); // Set it with the file size. This header is optional. It will work if it's omitted, but the download progress will be unknown.
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // The Save As popup magic is done here. You can give it any file name you want, this only won't work in MSIE, it will use current request URL as file name instead.
OutputStream output = ec.getResponseOutputStream();
// Now you can write the InputStream of the file to the above OutputStream the usual way.
// ...
fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}
通用JSF1.x示例
public void download() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
response.reset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
response.setContentType(contentType); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
response.setContentLength(contentLength); // Set it with the file size. This header is optional. It will work if it's omitted, but the download progress will be unknown.
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // The Save As popup magic is done here. You can give it any file name you want, this only won't work in MSIE, it will use current request URL as file name instead.
OutputStream output = response.getOutputStream();
// Now you can write the InputStream of the file to the above OutputStream the usual way.
// ...
fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}
4条答案
按热度按时间tjjdgumg1#
导言
你可以把一切都搞定
ExternalContext
. 在JSF1.x中,您可以获得原始HttpServletResponse
反对ExternalContext#getResponse()
. 在JSF2.x中,您可以使用一系列新的委托方法,如ExternalContext#getResponseOutputStream()
而不需要抓住HttpServletResponse
从jsf引擎罩下面。在响应上,您应该设置
Content-Type
标头,以便客户端知道要将哪个应用程序与提供的文件关联。而且,您应该设置Content-Length
标头,以便客户端可以计算下载进度,否则它将是未知的。而且,您应该设置Content-Disposition
标题至attachment
如果需要另存为对话框,否则客户端将尝试以内联方式显示该对话框。最后,只需将文件内容写入响应输出流。最重要的是打电话
FacesContext#responseComplete()
要通知jsf在您将文件写入响应后不应执行导航和呈现,否则响应的结尾将被页面的html内容污染,或者在较旧的jsf版本中,您将得到IllegalStateException
带着这样的信息getoutputstream() has already been called for this response
当jsf实现调用getWriter()
以呈现html。关闭ajax/不要使用远程命令!
您只需要确保操作方法不是由ajax请求调用的,而是在启动时由普通请求调用的
<h:commandLink>
及<h:commandButton>
. ajax请求和远程命令由javascript处理,由于安全原因,javascript没有强制与ajax响应内容进行另存为对话的功能。如果您正在使用例如primefaces
<p:commandXxx>
,然后需要确保通过显式关闭ajaxajax="false"
属性如果您使用的是icefaces,那么您需要嵌套一个<f:ajax disabled="true" />
在命令组件中。通用JSF2.x示例
通用JSF1.x示例
通用静态文件示例
如果需要从本地磁盘文件系统流式传输静态文件,请按以下方式替换代码:
通用动态文件示例
如果您需要对动态生成的文件(如pdf或xls)进行流式处理,只需提供
output
在这里,正在使用的api需要OutputStream
.e、 g.itext pdf:
e、 g.apache poi hssf:
请注意,您不能在此处设置内容长度。因此,您需要删除该行以设置响应内容长度。这在技术上没有问题,唯一的缺点是最终用户将收到未知的下载进度。如果这很重要,那么您确实需要首先写入本地(临时)文件,然后按照上一章所示提供它。
实用方法
如果您使用的是jsf实用程序库omnifaces,那么您可以使用三种方便的方法之一
Faces#sendFile()
方法采用File
,或InputStream
,或byte[]
,并指定是否应将文件作为附件下载(true
)或内联(false
).是的,此代码按原样完整。您不需要调用
responseComplete()
你自己也是。此方法还正确处理ie特定的头和utf-8文件名。你可以在这里找到源代码。xjreopfe2#
6bc51xsx3#
这就是我的工作原理:
nsc4cvqm4#
下面是完整的代码片段http://bharatonjava.wordpress.com/2013/02/01/downloading-file-in-jsf-2/
如果希望在运行时生成文件,可以更改文件读取逻辑。