0

I'm trying to provide download links (that should also work for images in an img tag) in the style of

http://www.domain.example/download.jsf?id=123

and my solution so far looks like this: (copied from here: How to provide a file download from a JSF backing bean? )

GetFile.java

@ManagedBean
@ViewScoped
public class GetFile{

// property and getter

public void setId(String id) {

    FacesContext fc = FacesContext.getCurrentInstance();
    ExternalContext ec = fc.getExternalContext();

    ec.responseReset();
    ec.setResponseContentType(contentType); 
    ec.setResponseContentLength(contentLength);
    ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

    try (OutputStream output = ec.getResponseOutputStream()) {
        // Now you can write the InputStream of the file to the above
        // OutputStream the usual way.
        // ...

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    fc.responseComplete(); 
}

and my download.xhtml looks like this:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core">

    <f:metadata>
        <f:viewParam name="id" value="#{getFile.id}" />
    </f:metadata>

</html>

That works so far. But when I want to add additional parameters like

http://www.domain.example/download.jsf?id=123&format=txt

then I would have to consider the order in which the parameters are set and do this in the last setter. That would work but I don't find that a very pretty solution, so my question is, is there a better way to achieve this?

Any hints are very appreciated!

1 Answers1

0

Initiating the download in a setter is in general not a very good design and should only do its main purpose, to set a variable (and maybe some checking/conversion/etc related to setting).

To start the download you should create a new method in your backing bean that handles the download and use that method. So your bean should look something like this:

GetFile.java

@ManagedBean
@ViewScoped
public class GetFile {

    // properties, getter and setter

    public void download() {
        // your download code goes here
    }
}

This way you can use as many parameters as you want and pass them the way you did. In your download.xhtml you can call your bean method after passing the arguments like this:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core">

    <f:metadata>
        <f:viewParam name="id" value="#{getFile.id}" />
        <!-- your other parameters come here -->
    </f:metadata>
    #{getFile.download()}
</html>
Java Doe
  • 346
  • 2
  • 6