Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

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!