9

I'm using Primefaces

p:fileDownload

to download a file which is not in class path.
So I'm passing FileInputStream as parameter to DefaultStreamedContent.
Every thing works fine when my bean is kept at @SessionScoped...,
But

java.io.NotSerializableException: java.io.FileInputStream

is thrown when I keep my bean in @Viewscoped.

My Code:

DownloadBean.java

@ManagedBean
@ViewScoped
public class DownloadBean implements Serializable {

    private StreamedContent dFile;

    public StreamedContent getdFile() {
        return dFile;
    }

    public void setdFile(StreamedContent dFile) {
        this.dFile = dFile;
    }

    /**
     * This Method will be called when download link is clicked
     */
    public void downloadAction()
    {
        File tempFile = new File("C:/temp.txt");
        try {
            dFile = new DefaultStreamedContent(new FileInputStream(tempFile), new MimetypesFileTypeMap().getContentType(tempFile));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

}

index.xhtml

<h:form>
    <h:commandLink action="#{downloadBean.downloadAction}">
        Download
        <p:fileDownload value="#{downloadBean.dFile}"/>
    </h:commandLink>
</h:form>

Isn't there any method to make it work?

4

1 回答 1

14

NotSerializableException抛出是因为视图范围由 JSF 视图状态表示,在服务器端状态保存的情况下,该视图状态又可以序列化为 HTTP 会话,或者在客户端状态保存的情况下可以序列化为 HTML 隐藏输入字段。FileInputStream绝不能以序列化的形式表示。

如果您绝对需要保持 bean 视图的范围,那么您不应该将其声明StreamedContent为实例变量,而是在 getter 方法中重新创建它。诚然,在 getter 方法中执行业务逻辑通常是不受欢迎的,但这StreamedContent是一个相当特殊的情况。在 action 方法中,您应该只准备稍后在DefaultStreamedContent构造期间使用的可序列化变量。

@ManagedBean
@ViewScoped
public class DownloadBean implements Serializable {

    private String path;
    private String contentType;

    public void downloadAction() {
        path = "C:/temp.txt";
        contentType = FacesContext.getCurrentInstance().getExternalContext().getMimeType(path);
    }

    public StreamedContent getdFile() throws IOException {
        return new DefaultStreamedContent(new FileInputStream(path), contentType);
    }

}

(请注意,我还修复了获取内容类型的方法;通过这种方式,您可以更自由地通过<mime-mapping>中的条目配置 mime 类型web.xml

顺便说一句,<p:graphicImage>StreamedContent. 另请参阅使用 p:graphicImage 和 StreamedContent 显示来自数据库的动态图像

于 2013-04-12T11:40:40.170 回答