如何在java web应用程序中将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 (当您想要弹出另存为对话框时)或inline (当您想让webbrowser处理显示自己)。 最后,您需要确保之后调用FacesContext#responseComplete()以避免IllegalStateException飞来飞去。

开球示例:

 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[] ,我建议使用它来代替从内存中保存webapp。 然后,您可以使用通常的Java IO方式在着名的InputStreamOutputStream循环中编写它。

您只需将mime类型设置为application/x-pdf到您的响应中即可。 您可以使用setContentType(String contentType)方法在servlet案例中执行此操作。
在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()); } } 

资源:

  • mimeapplication.net – pdf
  • Javadoc – ServletResponse
  • Javadoc – HttpServlet

使用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)). } 

此外,您还可以考虑以下其他一些事项:

  • 在HttpServletResponse中设置内容类型以通知浏览器您正在发送PDF数据:response.setContentType(“application / pdf”);
  • 使用context.responseComplete()方法通知FacesContext您将数据直接发送给用户。 这可以防止JSF执行不必要的额外处理。