java - 在 JSF 中下载 PDF 返回空白页

标签 java jsf

我使用 JSF,并且有一个 h:commandButton 来提示下载文件。该文件为 PDF 格式。下载的文件有正确的页数,但它们是空白的。

当文件在浏览器中打开时,我收到以下消息:

This PDF document might not be displayed correctly.

这是我的命令按钮:

    <h:form>
        <h:commandButton action="#{fileDownloadView.fileDownloadView}" value="Download"/>
    </h:form>

这是我的课:

@ManagedBean
public class FileDownloadView {

    private static final String FILENAME = "manual.pdf";
    private static final String CONTENT_TYPE = "application/pdf";

    public FileDownloadView() throws IOException, DocumentException {
        Resource resource = new ClassPathResource(FILENAME);
        InputStream stream = resource.getInputStream();
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        externalContext.responseReset();
        externalContext.setResponseContentType(CONTENT_TYPE);
        externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + FILENAME + "\"");
        OutputStream outputStream = externalContext.getResponseOutputStream();
        byte[] bytes = IOUtils.toByteArray(stream);
        outputStream.write(bytes);
        facesContext.responseComplete();
    }

}

这可能是什么原因造成的?

编辑:

声称重复的帖子给出了这段代码:

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.
}

如果你仔细观察,我的代码是相同的,除了注释部分写道:

// Now you can write the InputStream of the file to the above OutputStream the usual way. // ...

我为此写的是

byte[] bytes = IOUtils.toByteArray(stream);
outputStream.write(bytes);

这有什么问题吗?那不是写入输出流中的字节数组吗?为什么这不起作用?

最佳答案

你是对的,你的bean的构造函数的主体与示例中给出的下载方法的主体相同。

您的命令链接<h:commandButton action="#{fileDownloadView.fileDownloadView}" .../>操作方法表达式正在尝试查找并调用名为fileDownloadView方法在您的 bean 上,但该方法不存在。

您的public FileDownloadView是一个构造函数,因为它没有返回值类型并且与类同名。如果您将其更改为 public void download该 bean 将不再有显式构造函数,但最终有一个可以通过命令按钮调用的方法,如下所示:

 <h:commandButton action="#{fileDownloadView.download}" value="Download"/>

大小写很重要,所以不要调用方法 public void Download或类似的。

我不确定您当前的实现中实际发生了什么,但我猜虽然 #{fileDownloadView.fileDownloadView}正在解决,创建了一个新的 bean 实例 fileDownloadView从表达式的第一部分开始,构造函数中的代码已成功执行。一些 CPU 周期之后,ELResolver 无法解析第二个 .fileDownloadView表达式的一部分并引发异常,这会搞乱事情。

关于java - 在 JSF 中下载 PDF 返回空白页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54399198/

相关文章:

jsf - 如何在 IBM Websphere Portal 6.1 JSF Portlet 中传递和获取 URL 参数?

java - 为什么我们不能通过未初始化的局部变量访问静态内容?

css - 动态 Web 元素 Eclipse 的 XHTML 文件中的 CSS 如何以及在何处

java - 领域模型和实体模型是否相同

java - 当我对我之前在代码中执行过的同一 WebElement 执行 click() 时,出现空指针异常

javascript - 特立尼达的屏蔽输入字段

jsf - 从请求作用域 bean 访问 session 作用域 bean

Java Applet/Javascript - 通过网络打印 pdf 时如何操作打印设置?

java - 读取文件时未报告的异常 FileNotFoundException

java - 自动检测用户所在的国家