1

I have a datatable which allows you to download files. It works. However when I try to download a file after filtering returned is first on the list.

This image shows that when clicked on teste4.txt the same file was downloaded. This is correct. Correct download

This other picture shows that when clicked on file teste4.txt, after filtering, the downloaded file was teste1.txt Download wrong

This is my file containing the datatable:

<h:form id="hFormListaArquivosRegiao2" enctype="multipart/form-data">

    <p:dataTable id="pDataTableListaArquivos" var="arquivo" value="#{arquivoBean.listaArquivos}" filteredValue="#{arquivoBean.filteredListaArquivos}">

        <p:column id="pColumnNomeArquivo" headerText="#{msg.NomeDoArquivo}" sortBy="#{arquivo.nomeArquivo}" filterMatchMode="contains" filterBy="#{arquivo.nomeArquivo}">

            <h:commandLink action="#{arquivoBean.download}" title="#{arquivo.nomeArquivo}">

                <h:outputText value="#{arquivo.nomeArquivo}" />
                <f:setPropertyActionListener target="#{arquivoBean.arquivo}" value="#{arquivo}" />

            </h:commandLink>

        </p:column>

</h:form>

This is the method of backingBean responsible for downloading:

public void download() throws Exception {

    logger.debug("NOME ARQUIVO: "+ ContextoBean.CAMINHO_ARQUIVOS + arquivo.getNomeArquivo() +", "+ arquivo.getNomeArquivo());

    FacesContext facesContext = FacesContext.getCurrentInstance();
    pushArquivo(facesContext.getExternalContext(), ContextoBean.CAMINHO_ARQUIVOS + arquivo.getNomeArquivo(), arquivo.getNomeArquivo());
    facesContext.responseComplete();

}

This is the helper method of backingBean responsible for downloading:

private void pushArquivo(ExternalContext externalContext, String nomeArquivo, String nomeDeExibicao) throws IOException {

    // Info sobre a lógica usada: http://stackoverflow.com/questions/1686821/execute-backing-bean-action-on-load
    File descritoArquivo = new File(nomeArquivo);
    int length = 0;
    OutputStream os = externalContext.getResponseOutputStream();
    String extencaoArquivo = externalContext.getMimeType(nomeArquivo);
    externalContext.setResponseContentType((extencaoArquivo != null) ? extencaoArquivo : "application/octet-stream");
    externalContext.setResponseContentLength((int) descritoArquivo.length());
    externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + nomeDeExibicao + "\"");

    // Stream to the requester.
    byte[] bbuf = new byte[1024];
    DataInputStream in = new DataInputStream(new FileInputStream(descritoArquivo));
    while ((in != null) && ((length = in.read(bbuf)) != -1)) {
        os.write(bbuf, 0, length);
    }

    in.close();

}

Sant
  • 386
  • 2
  • 6
  • 17
  • Have you tried using Primefaces' [download component](http://www.primefaces.org/showcase/ui/fileDownload.jsf)? It should be compatible with their own filters – Rodrigo Sasaki Apr 03 '13 at 18:09
  • Yes, I've tried. I implemented something like this: [Primefaces p:fileDownload with datatable](http://stackoverflow.com/questions/14144306/primefaces-pfiledownload-with-datatable) – Sant Apr 03 '13 at 18:14

1 Answers1

0

If I were you I would make a few changes to get the current arquivo by method parameter :

<h:commandLink action="#{arquivoBean.download(arquivo)}">
    <h:outputText value="#{arquivo.nomeArquivo}" />
</h:commandLink>

In the bean :

public void download(Arquivo arquivo) throws Exception {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    pushArquivo(facesContext.getExternalContext(),
        ContextoBean.CAMINHO_ARQUIVOS + arquivo.getNomeArquivo(),
        arquivo.getNomeArquivo());
    facesContext.responseComplete();
}
Alexandre Jacob
  • 2,993
  • 3
  • 26
  • 36
  • This solution has generated an exception: WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http-localhost-127.0.0.1-8080-3) #{arquivoBean.download(arquivo)}: java.lang.NullPointerException: javax.faces.FacesException: #{arquivoBean.download(arquivo)}: java.lang.NullPointerException – Sant Apr 08 '13 at 16:10
  • What is you JSF implementation? – Alexandre Jacob Apr 08 '13 at 19:02
  • My implementation is Mojarra 2.0 – Sant Apr 08 '13 at 19:12
  • I'm almost getting. Now I can get the correct object. The problem now is that the download window does not open. My commandLink was so: #{arquivo.nomeArquivo} – Sant Apr 08 '13 at 19:19
  • and the download method looked like this: FacesContext context = FacesContext.getCurrentInstance(); Map map = context.getExternalContext().getRequestParameterMap(); String codigoArquivo = (String) map.get("codigoArquivo"); String criterioListaArquivosParam = (String) map.get("criterioListaArquivosParam"); ArquivoRN arquivoRN = new ArquivoRN(); Arquivo arquivo = arquivoRN.busArquivo(codigoArquivo); – Sant Apr 08 '13 at 19:21
  • and this: FacesContext facesContext = FacesContext.getCurrentInstance(); pushArquivo(facesContext.getExternalContext(), ContextoBean.CAMINHO_ARQUIVOS + criterioListaArquivosParam + arquivo.getNomeArquivo(), arquivo); facesContext.responseComplete(); – Sant Apr 08 '13 at 19:22
  • the push method I just changed the signature: String nomeDeExibicao to Arquivo arquivo – Sant Apr 08 '13 at 19:24
  • and modified: externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + nomeDeExibicao.getNomeArquivo() + "\""); to externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + arquivo.getNomeArquivo() + "\""); – Sant Apr 08 '13 at 19:26