16

which is the right way to download a file using JSF?, just putting a link to the file ?? in that case how do i get the file URL??

i have seen one example using BufferedInputStream:

http://www.winstonprakash.com/articles/jsf/file_download_link.htm

What are the differences?

Thanks

ErVeY
  • 1,524
  • 4
  • 16
  • 26

3 Answers3

25

If it's a simple file, just place in public webcontent (there where you put your static and JSF files) and create a link.

<h:outputLink value="/files/file.ext">link</h:outputLink>

The servletcontainer will worry about applying the correct headers.

If it's located outside the public webcontent for some specific reasons (e.g. in a fixed path at server machine, or in a database), then create a servlet which gets an InputStream of it and writes it to the OutputStream of the response along at least the Content-Type, Content-Disposition and Content-Length headers. You can find here a simple kickoff example. Also that can simply be linked on the servlet's url-pattern.

If it's to be dynamically generated and depending on the JSF specific request parameters, then you can also do so in a managed bean action which is bound by h:commandLink or h:commandButton, but you only need to ensure that you call FacesContext#responseComplete() at end of bean's action method to prevent JSF from taking the navigation in hands. The same kind of servlet code can be reused to stream the file. You can find a kickoff example in this answer.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • O.o Thx BalusC I couldn't connect in all the weekend, but i have to thank you for all your help =D I really appreciate – ErVeY Aug 09 '10 at 13:34
14

I needed to make a similar code to download a file via JSF

That's my download button in my JSF page

<h:commandButton value="Download" action="#{helloBean.downloadFile}" />

And it's my Java Code

public void downloadFile() {

    File file = new File("/home/marco/file.txt");
    HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();  

    response.setHeader("Content-Disposition", "attachment;filename=file.txt");  
    response.setContentLength((int) file.length());  
    ServletOutputStream out = null;  
    try {  
        FileInputStream input = new FileInputStream(file);  
        byte[] buffer = new byte[1024];  
        out = response.getOutputStream();  
        int i = 0;  
        while ((i = input.read(buffer)) != -1) {  
            out.write(buffer);  
            out.flush();  
        }  
        FacesContext.getCurrentInstance().getResponseComplete();  
    } catch (IOException err) {  
        err.printStackTrace();  
    } finally {  
        try {  
            if (out != null) {  
                out.close();  
            }  
        } catch (IOException err) {  
            err.printStackTrace();  
        }  
    }  

}
  • 3
    Shouldn't the action method of the command button return a String? – codingsplash Aug 23 '13 at 09:34
  • 3
    I think there is an error in this answer. You have to call `FacesContext.getCurrentInstance().responseComplete()` at the end (and not `getResponseComplete`) – LaurentG Mar 18 '19 at 19:57
-1

I have had an error on

FacesContext.getCurrentInstance().getResponseComplete(); 

from the type

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

and i solved it:

JSF page:

<h:commandButton action="#{bean.downloadFile}" id="downloadBtn" value="Download"/>

Bean method:

public void downloadFile(File file) {   
    FacesContext facesContext = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
    response.setHeader("Content-Disposition", "attachment;filename=file.txt");
    response.setContentLength((int) file.length());
    FileInputStream input= null;
    try {
        int i= 0;
        input = new FileInputStream(file);  
        byte[] buffer = new byte[1024];
        while ((i = input.read(buffer)) != -1) {  
            response.getOutputStream().write(buffer);  
            response.getOutputStream().flush();  
        }               
        facesContext.responseComplete();
        facesContext.renderResponse();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(input != null) {
                input.close();
            }
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}
  • I said try cause i had no time to explain it well and the title of the post is [ Download a file with JSF?]. And i have tested it and it works so if you have no tested please dont tell i think... – Manuel Outeiriño Sep 07 '15 at 05:45