我使用的是Primefaces
号码:fileDownload
下载不在类路径中的文件
所以我将 FileInputStream 作为参数传递给 DefaultStreamedContent 。
当我的bean被保存在 @SessionScoped ......时,每件事都可以正常工作
但是
当我将bean保存在 @Viewscoped 中时,会抛出java.io.NotSerializableException:java.io.FileInputStream
。
我的代码:
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>
还有什么方法可以让它发挥作用吗?
答案 0 :(得分:13)
抛出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>
中的web.xml
条目以更加自由的方式配置mime类型 < / p>
<p:graphicImage>
与StreamedContent
的问题完全相同。另见其他Display dynamic image from database with p:graphicImage and StreamedContent。