我正在使用Primefaces
下载不在类路径中的文件。
因此,我将 FileInputStream 作为参数传递给 DefaultStreamedContent 。
当我的bean保留在 @SessionScoped ...时,一切正常。
但
当我将bean放在 @Viewscoped 中时抛出该错误。
我的代码:
下载Bean.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>
没有任何使它起作用的方法吗?
最佳答案
之所以抛出NotSerializableException
,是因为该 View 范围由JSF View 状态表示,如果服务器端状态保存,则可以依次序列化为HTTP session ;如果保存客户端状态,则可以隐藏为HTML隐藏的输入字段。 FileInputStream
绝对不能以序列化形式表示。
如果您绝对需要使Bean View 保持作用域,则不应将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:graphicImage>
与StreamedContent
有着完全相同的问题。另请参见Display dynamic image from database with p:graphicImage and StreamedContent。