【发布时间】:2010-08-28 19:06:03
【问题描述】:
在行动方法(JSF)中,我有如下内容:
public String getFile() {
byte[] pdfData = ...
// how to return byte[] as file to web browser user ?
}
如何将 byte[] 作为 pdf 格式发送到浏览器?
【问题讨论】:
在行动方法(JSF)中,我有如下内容:
public String getFile() {
byte[] pdfData = ...
// how to return byte[] as file to web browser user ?
}
如何将 byte[] 作为 pdf 格式发送到浏览器?
【问题讨论】:
在 action 方法中,您可以通过 ExternalContext#getResponse() 从 JSF 引擎盖下获取 HTTP servlet 响应。然后您需要至少将 HTTP Content-Type 标头设置为 application/pdf 并将 HTTP Content-Disposition 标头设置为 attachment(当您想要弹出 另存为 对话框时)或 @987654328 @(当您想让网络浏览器自己处理显示时)。最后,你需要确保你之后调用FacesContext#responseComplete(),以避免IllegalStateExceptions 飞来飞去。
启动示例:
public void download() throws IOException {
// Prepare.
byte[] pdfData = getItSomehow();
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
// Initialize response.
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("application/pdf"); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
response.setHeader("Content-disposition", "attachment; filename=\"name.pdf\""); // The Save As popup magic is done here. You can give it any filename you want, this only won't work in MSIE, it will use current request URL as filename instead.
// Write file to response.
OutputStream output = response.getOutputStream();
output.write(pdfData);
output.close();
// Inform JSF to not take the response in hands.
facesContext.responseComplete(); // Important! Else JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}
也就是说,如果您有可能将 PDF 内容作为 InputStream 而不是 byte[],我建议您使用它来保存 web 应用程序以防止内存占用。然后,您只需按照通常的 Java IO 方式将其写入众所周知的 InputStream-OutputStream 循环即可。
【讨论】:
您只需在回复中将 mime 类型设置为 application/x-pdf。您可以在 servlet 案例中使用 setContentType(String contentType) 方法来执行此操作。
在 JSF/JSP 中,您可以在编写响应之前使用它:
<%@ page contentType="application/x-pdf" %>
和response.write(yourPDFDataAsBytes()); 写入您的数据。
但我真的建议你在这种情况下使用 servlet。 JSF 用于呈现 HTML 视图,而不是 PDF 或二进制文件。
使用 servlet,您可以使用它:
public MyPdfServlet extends HttpServlet {
protected doGet(HttpServletRequest req, HttpServletResponse resp){
OutputStream os = resp.getOutputStream();
resp.setContentType("Application/x-pdf");
os.write(yourMethodToGetPdfAsByteArray());
}
}
资源:
【讨论】:
使用JSF向浏览器发送原始数据时,需要从FacesContext中提取HttpServletResponse。
使用HttpServletResponse,您可以使用标准 IO API 将原始数据发送到浏览器。
这是一个代码示例:
public String getFile() {
byte[] pdfData = ...
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
OutputStream out = response.getOutputStream();
// Send data to out (ie, out.write(pdfData)).
}
此外,您可能还需要考虑以下一些其他事项:
【讨论】: