2010-08-28 82 views

回答

49

在action方法中,您可以从JSF引擎盖下获得HTTP servlet响应ExternalContext#getResponse()。然后,你需要至少设置HTTP Content-Typeapplication/pdf和HTTP Content-Dispositionattachment(当你想弹出一个另存为对话),或inline(当你想要让网页浏览器处理显示本身)。最后,您需要确保您以后拨打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[],我会建议使用,而不是从内存猪保存Web应用程序。然后,您只需在熟知的InputStream - OutputStream循环中将其写入常用的Java IO方式。

+0

非常感谢:),但我不能投票(声誉)。 – marioosh 2010-08-28 22:02:25

+0

感谢您发布此信息。 – 2011-08-15 07:44:16

+0

刚刚发现需要什么。谢谢。 – user 2012-12-11 09:03:37

5

你只需要MIME类型来设置application/x-pdf到你的回应。您可以使用setContentType(String contentType)方法在servlet案例中执行此操作。
在JSF/JSP,你可以写你的响应之前使用,:

<%@ page contentType="application/x-pdf" %> 

response.write(yourPDFDataAsBytes());写你的数据。
但我真的建议你在这种情况下使用servlets。 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()); 
    } 
} 

资源:

+0

从一点经验来看,浏览器比application/x-pdf更好地处理application/pdf。 – 2011-12-23 11:15:42

1

使用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执行不必要的额外处理。
相关问题