How to use Streamed Content with p:fileDownload to Download Non class path File

jsf, primefaces

Solution

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.

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);
    }

}

(note that I also fixed your way to get the content type; you have this way much more freedom to configure mime types via `<mime-mapping>` entries in `web.xml`)

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.

Problem

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?

Original source

Related problems