Solucionado (ver solução)
Solucionado
(ver solução)
10
respostas

fileUpload e fileDownload

Olá, Em minha aplicação estou usando fileUpload e fileDownload do primeface, como faço para listar em uma datatable os arquivos que esta em um diretorio e também conter um botão fileDownload que baixe o arquivo daquela linha da datatable, ou até mesmo uma datalist?

10 respostas

Opa, a ideia é que você estes caminhos salvos em algum lugar. você vai listar essas informações e aí pode criar um servlet de download que recebe o id do registro ou o caminho como parâmetro, carrega o arquivo e disponibiliza para download. Aqui tem um exemplo de código da servlet => https://www.mkyong.com/servlet/servlet-code-to-download-text-file-from-website-java/

No caso eu já consegui listar os arquivos em uma dataTable, agora como faço para que o botão de fileDownload ache o arquivo ao qual esta na mesma linha e faça o download?

Eu tenho o dowload assim:

@ManagedBean
public class FileDownloadView {

    private StreamedContent file;

    public FileDownloadView() {        
        InputStream stream = FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/fotos/teste.jpg");
        file = new DefaultStreamedContent(stream, "image/jpg", "downloaded_teste.jpg");
    }

    public StreamedContent getFile() {
        return file;
    }
}

Assim ele esta statico, so esta achando o "teste.jpg" .Como eu faria para ele procurar o arquivo listado nessa classe abaixo e fazer o download:

private String arquivo;

    private List<Arquivo> listArquivos;

    public String getArquivo() {
        return arquivo;
    }

    public void setArquivo(String arquivo) {
        this.arquivo = arquivo;
    }


    String caminho = "C:\\Users\\felipe.vasconcellos\\Documents\\TesteWEB\\web\\fotos\\";

    public List<Arquivo> teste() {

        listArquivos = new ArrayList<Arquivo>();

        File file = new File(caminho);
    File afile[] = file.listFiles();
    int i = 0;
    for (int j = afile.length; i < j; i++) {
        File arquivos = afile[i];
        System.out.println(arquivos.getName());

                listArquivos.add(new Arquivo(arquivos.getName()));

        }

        return listArquivos;
    }

    public void handleFileUpload(FileUploadEvent event) {
        FacesMessage message = new FacesMessage("Sucesso", event.getFile().getFileName() + " seu uploaded.");
        FacesContext.getCurrentInstance().addMessage(null, message);

        byte[] conteudo = event.getFile().getContents();  
    FileOutputStream fos;
        try {

            String caminho = "C:\\Users\\felipe.vasconcellos\\Documents\\TesteWEB\\web\\fotos\\";

            fos = new FileOutputStream(caminho + event.getFile().getFileName());
            fos.write(conteudo);
            fos.close();

        } catch (Exception ex) {
            Logger.getLogger(cadastroAnimalController.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public List<Arquivo> getListArquivos() {

        teste();

        return listArquivos;
    }

    public void setListArquivos(List<Arquivo> listArquivos) {
        this.listArquivos = listArquivos;
    }

Fala Felipe tudo bem?

Fazendo pelo Managed Bean, você acabaria recebendo uma página como resposta e o que você quer é o arquivo.

Usando o Servlet que o Alberto passou na resposta acima, você consegue linkar o download do datatable com esse Servlet.

Espero ter ajudado

Samir, Eu não queria usar uma Servlet, deve ter uma maneira mais simples eu acho, porque hoje eu tenho esse metodo

@ManagedBean
public class FileDownloadView {

    private StreamedContent file;

    public FileDownloadView() {        
        InputStream stream = FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/fotos/teste.jpg");
        file = new DefaultStreamedContent(stream, "image/jpg", "downloaded_teste.jpg");
    }

    public StreamedContent getFile() {
        return file;
    }
}

como faço para ele busca o arquivo correto sem precisar especificar o nome do arquivo, porque eu tenho uma database, e nela possui uma lista de arquivos, mas nesse metodo eu só consigo fazer download de um arquivo.

Felipe, como vc está montando a sua dataTable?

O que talvez vc pudesse fazer era passar o parametro do método getResourceAsStream() atraves da sua view.

Você pode passar o código da sua view?

Tela XHTML

<p:dataTable value="#{cadastroAnimalController.listArquivos}" var="car" style="background: none;"
                         filteredValue="#{cadastroAnimalController.listArquivos}">
                <h:outputText value="#{car.nomeArquivo}" />
                <p:column headerText="Id">
                    <h:outputText value="#{car.nomeArquivo}" />
                </p:column>

                <p:column headerText="Download">
                    <p:commandButton value="Download" ajax="false" onclick="PrimeFaces.monitorDownload(start, stop);" icon="ui-icon-arrowthick-1-s">
                        <p:fileDownload value="#{fileDownloadView.file}" />
                    </p:commandButton>
                </p:column>

            </p:dataTable>

Felipe, tenta colocar esse actionListener na sua view:

<p:column headerText="Download">
<p:commandButton value="Download" ajax="false" actionListener="#{fileDownloadView.prepararArquivo(arquivo)}" onclick="PrimeFaces.monitorDownload(start, stop);" icon="ui-icon-arrowthick-1-s">
    <p:fileDownload value="#{fileDownloadView.file}" />
</p:commandButton>
</p:column>

e esse método no seu MB (fileDownloadView):

private StreamedContent file;
private InputStream stream;

public void prepararArquivo(Arquivo arquivo) {

    String nome = arquivo.getName();

    stream = FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/fotos/" + nome);
    file = new DefaultStreamedContent(stream, "image/jpg", nome);

}

public StreamedContent getFile() {
    System.out.println("File: " + file.getName());
    return file;
}

Samir, O netBeans pede para eu criar o metodo getName() na minha classe Arquivo.

Minha classe Arquivo:

public class Arquivo {

    private String nomeArquivo;

    public Arquivo(String nomeArquivo) {
        this.nomeArquivo = nomeArquivo;
    }

    public String getNomeArquivo() {
        return nomeArquivo;
    }

    public void setNomeArquivo(String nomeArquivo) {
        this.nomeArquivo = nomeArquivo;
    }

}

eu substitui o seu getName() pelo getNomeArquivo() da classe Arquivo, mas quando eu cliquei no commandButton de Download deu erro:

Advertência:   /index.xhtml @38,191 actionListener="#{fileDownloadView.prepararArquivo(arquivo)}": java.lang.NullPointerException

Fiz certo em substituir ou esse getName() tem que ser criado de outra forma?

solução!

provavelmente é porque ele não esta achando o parametro arquivo.

<p:commandButton value="Download" ajax="false" actionListener="#{fileDownloadView.prepararArquivo(car)}" onclick="PrimeFaces.monitorDownload(start, stop);" icon="ui-icon-arrowthick-1-s">
    <p:fileDownload value="#{fileDownloadView.file}" />
</p:commandButton>insira seu código aqui

temos que passar a variavel que setamos no dataTable.

Tenta trocando esse parametro e usa o getNomeArquivo() no lugar do getName().

Deu certo, Obrigado Samir!