4

Hello I'm doing File upload and download same file operation using JSF and Primefaces.

I'm using techniques from different forums and blogs combined(BelusC 's blog and Primefaces Showcase).

The main idea of this operation is to let user to upload a file and generate a Download link for the uploaded file so that he can download and see it before Submitting.

Here is my code:

index.xhtml

<h:form>
    <p:fileUpload showButtons="false" label="Attach Refrral" 
        auto="true" fileUploadListener="#{fileBean.uploadListener}"/>
</h:form>

<h:form >
   <p:commandLink>
      See Uploaded File
      <p:fileDownload value="#{fileBean.refrralFile}"/>
   </p:commandLink>
</h:form>

FileBean.java

private StreamedContent refrralFile;


    public void uploadListener(FileUploadEvent evt)throws Exception
    {
        UploadedFile fx = evt.getFile();

        File mainDir = new File("C:/","fileStorage");
        if(!mainDir.exists())
        {
            mainDir.mkdir();
        }
        File subDir = new File(mainDir,"AttachedRefrrals");
        if(!subDir.exists())
        {
            subDir.mkdir();
        }
        String fileName = fx.getFileName();

        File f = new File(subDir,fileName);
        FileOutputStream fos = new FileOutputStream(f);
        IOUtils.copy(fx.getInputstream(), fos);

        InputStream is = ((ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext()).getResourceAsStream(f.getAbsolutePath());
        refrralFile  = new DefaultStreamedContent(is, new MimetypesFileTypeMap().getContentType(f), fileName);

    }


    public StreamedContent getRefrralFile() {
        return refrralFile;
    }

Using above code File is uploading Successfully but if I click file download link ths throwing exception:

java.lang.IllegalStateException: getOutputStream() has already been called for this response

I used FacesContext#responseComplete(), as its been suggested many places, now download link is not working at all.

Please correct me if I'm wrong in my technique or code and suggest any better way if you know.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Kishor Prakash
  • 8,011
  • 12
  • 61
  • 92

1 Answers1

12

The <p:commandLink> fires by default an ajax request. You can't download files via ajax. JavaScript, who's responsible for processing the ajax request, has no clue what to do with retrieved binary file which is quite different from the expected XML response. JavaScript has for obvious security reasons no facilities to trigger a Save As dialogue with arbitrary content.

So, to fix your concrete problem, use

<p:commandLink ajax="false">

or just

<h:commandLink>

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I'll try and see that. But is the coding technique I'm using is good one? or any better less painful way is there?? – Kishor Prakash Apr 10 '13 at 12:28
  • The right place for code reviews is http://codereview.stackexchange.com. I'm not sure what you mean with "painful". I won't go in this ungrounded subjectiveness. I can at least tell that this code leaves resources open and doesn't deal with an IE-specific quirk on file name. This is however beyond the question. – BalusC Apr 10 '13 at 12:30
  • Thanks very very much BelusC. **IT WORKED**. Will it be ok if I close all the streams I opened? What do you mean by IE-specific quirk. – Kishor Prakash Apr 10 '13 at 13:18
  • See also http://stackoverflow.com/questions/15728320/event-getfile-getfilename-is-returning-filename-with-complete-path-in-jsf2-0 and http://stackoverflow.com/questions/14211843/how-to-save-uploaded-file/14214223#14214223 – BalusC Apr 10 '13 at 13:25