Download a file using RichFaces

I already have the following:

  • User can upload file (i.e. compressed archive)
  • User can unzip the file on the server
  • The user can perform some actions in these files, which leads to the creation of more files

Now I need to do step 4:

  • User can download files to their computer again

Can someone tell me? I tried to understand what I found on Google, but it does not work as expected. Should I set the content type? When I install the application / octet stream, only txt and csv files will display correctly (in the browser, and not as a popup download window, as I wanted), other files will not work ...

JSP:

<a4j:commandLink value="Download" action="#{appController.downloadFile}" rendered="#{!file.directory}">
   <f:param name="file" value="#{file.absoluteFilename}" />
</a4j:commandLink>

AppController:

public String downloadFile() {
    String filename = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("file");
    File file = new File(filename);
    HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();  

    writeOutContent(response, file, file.getName());

    FacesContext.getCurrentInstance().responseComplete();
    return null;
}

private void writeOutContent(final HttpServletResponse res, final File content, final String theFilename) {
    if (content == null) {
        return;
    }
    try {
        res.setHeader("Pragma", "no-cache");
        res.setDateHeader("Expires", 0);
        res.setHeader("Content-disposition", "attachment; filename=" + theFilename);
        FileInputStream fis = new FileInputStream(content);
        ServletOutputStream os = res.getOutputStream();
        int bt = fis.read();
        while (bt != -1) {
            os.write(bt);
            bt = fis.read();
        }
        os.flush();
        fis.close();
        os.close();
    } catch (final IOException ex) {
        Logger.getLogger(ApplicationController.class.getName()).log(Level.SEVERE, null, ex);
    }
}
+5
source
3

, Ajax. . JavaScript - " ". , -, .

<h:commandLink value="Download" action="#{appController.downloadFile}" rendered="#{!file.directory}">
   <f:param name="file" value="#{file.absoluteFilename}" />
</h:commandLink>

, , ServletContext#getMimeType() <mime-mapping> web.xml ( , webapp one).

ServletContext servletContext = (ServletContext) externalContext.getContext();
String contentType = servletContext.getMimeType(file.getName());

if (contentType == null) {
    contentType = "application/octet-stream";
}

response.setContentType(contentType);
// ...

( , , JSF 1.x, , , , JSF 2.x ExternalContext#getMimeType())

+8

4 , :

  • HTML html-. a4j:htmlCommandLink ( h:commandLink , <f:param /> , ).

  • (), Content application/octet-stream.

  • , .

Backing Bean :

public void descargaArchivo() {
    //sorry but the programming standard says that we MUST declare
    //our variables at the beginning of any function =(
    HttpServletResponse objResponse;
    FileInputStream objFileInputStream;
    String strNombreCompletoArchivo, strNombreArchivo;
    byte[] arrDatosArchivo;
    try {
        //Here I get the <f:param> with the full name of the file. It encapsulates
        // the Faces.getCurrentInstance...  call.
        strNombreCompletoArchivo = UManejadorSesionWeb.obtieneParametro("nombreCompletoArchivo");
        //The function obtieneNombreArchivo retrieves the name of the file
        //based on the full name and the file separator (/ for Windows, \ for Linux)
        strNombreArchivo = UFuncionesGenerales.obtieneNombreArchivo(strNombreCompletoArchivo);
        //Getting the response from Faces.getCurrentInstance... 
        objResponse = UManejadorSesionWeb.obtieneHttpResponse();
        //Setting up the response content type and header (don't set the length!)
        objResponse.setContentType("application/octet-stream");
        objResponse.setHeader("Content-Disposition", "attachment; filename=\"" + strNombreArchivo + "\"");
        //Create the FileInputStream for the file to download
        objFileInputStream = new FileInputStream(strNombreCompletoArchivo);
        //Setting the file on the response
        arrDatosArchivo = new byte[UConstante.BUFFER_SIZE];
        while(objFileInputStream.read(arrDatosArchivo, 0, UConstante.BUFFER_SIZE) != -1) {
           objResponse.getOutputStream().write(arrDatosArchivo, 0, UConstante.BUFFER_SIZE);
        }
        objFileInputStream.close();
        objResponse.getOutputStream().flush();
        objResponse.getOutputStream().close();
        //Telling the framework that the response has been completed.
        FacesContext.getCurrentInstance().responseComplete();
    } catch (Exception objEx) {
        //manage the errors...
    }
}
//The constant used for byte array size
public class UConstante {
    public static final int BUFFER_SIZE = 2048;
}

jsp :

<a4j:htmlCommandLink  rendered="#{documento.rutaDestino != null}"
    action="#{documentoRequerido.descargaArchivo}">
    <f:param name="nombreCompletoArchivo" value="#{documento.rutaDestino}" />
    <h:graphicImage value="/Resource/iconos/mover-abajo.png" styleClass="pic" />
</a4j:htmlCommandLink>

, .

: , , . Java IE8, Firefox 9 10 Chrome 16. .

P.S.: , , . , , , :).


EDIT: @lisa

,

//strNombreCompletoArchivo = UManejadorSesionWeb.obtieneParametro("nombreCompletoArchivo");
String parameterStr = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap.get("nombreCompletoArchivo");
strNombreCompletoArchivo = parameterStr;
+3

richface a4j: commandLink , jsf- h: commandLink .

, ( firebug firefox):

Content-Disposition; = "your_file_name.xxx"

Content-Type/xxx

Content-Length 1234

Content-Length: number of bytes.

+2
source

All Articles