如何使用带有 p:fileDownload 的流式内容下载非类路径文件 [英] How to use Streamed Content with p:fileDownload to Download Non class path File

查看:18
本文介绍了如何使用带有 p:fileDownload 的流式内容下载非类路径文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Primefaces

I'm using Primefaces

p:文件下载

下载不在类路径中的文件.
所以我将 FileInputStream 作为参数传递给 DefaultStreamedContent.
当我的 bean 保持在 @SessionScoped...,
时,一切正常但是

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

java.io.NotSerializableException: java.io.FileInputStream

在我将 bean 保留在 @Viewscoped 中时抛出.

is thrown when I keep my bean in @Viewscoped.

我的代码:

下载Bean.java

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

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?

推荐答案

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

The NotSerializableException is thrown because the view scope is represented by the JSF view state which can in turn be serialized to HTTP session in case of server side state saving or a HTML hidden input field in case of client side state saving. The FileInputStream can in no way be represented in a serialized form.

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

If you absolutely need to keep the bean view scoped, then you should not be declaring StreamedContent as an instance variable, but instead recreate it in the getter method. True, doing business logic in a getter method is usually frowned upon, but the StreamedContent is a rather special case. In the action method, you should then only prepare serializable variables which are later to be used during DefaultStreamedContent construction.

@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)

顺便说一下,StreamedContent 有完全相同的问题.另请参见使用 p:graphicImage 和 StreamedContent 显示数据库中的动态图像.

The <p:graphicImage> has by the way exactly the same problem with StreamedContent. See also among others Display dynamic image from database with p:graphicImage and StreamedContent.

这篇关于如何使用带有 p:fileDownload 的流式内容下载非类路径文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆