[Tutorial] upload e download com o JSF

Deu trabalho, mas finalmente consegui deixar o upload e o download com o JSF totalmente funcional, sem usar outro framework como o PrimeFaces.
Eu desenvolvi para que o download e o upload vem e vão para um banco de dados.

upload.xhtml

<h:form enctype="multipart/form-data">
                <h:outputLabel value="Arquivo: " for="arquivo"/>
                <h:inputFile value="#{arquivoBean.uploadPart}" id="uploadPart"/>
			<h:commandButton value="Upload" action="#{arquivoBean.uploadArquivo()}"/>
</h:form>

download.xhtml

<h:commandLink value="Baixar Arquivo" actionListener="#{arquivoBean.downloadArquivo(arquivo.id)}"/><br />

ArquivoBean.java, foi usado a lib commons-io-2.4.jar

@ManagedBean
public class ArquivoBean {
	
	private Manager setManager = new Manager();
    private UploadRepository repository = new UploadRepository();
	
    private Arquivo arquivo = new Arquivo();
    private Part arquivoPart;

    public void uploadArquivo() {
        try {
            this.arquivo.setArquivo(IOUtils.toByteArray(arquivoPart.getInputStream()));
            this.arquivo.setArquivoNome(pegarNomeDoArquivo(arquivoPart));
            this.arquivo.setArquivoTamanho(arquivoPart.getSize());
        } catch (IOException ex) {
            Logger.getLogger(ArquivosBean.class.getName()).log(Level.SEVERE, null, ex);
        }
        repository.adiciona(this.arquivo);
        this.arquivo = new Arquivo();
    }
	
	    public void downloadArquivo(Long id) throws IOException {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletResponse response = this.setManager.response(facesContext);
		
        Arquivo arquivo = repository.baixarArquivo(id);

        response.reset(); 
        response.setContentType("application/octet-stream");
        response.setContentLength(arquivo.getArquivo().length);
        response.setHeader("Content-disposition", "attachment; filename=" + arquivo.getArquivoNome());

        OutputStream output = response.getOutputStream();
        output.write(arquivo.getArquivo());
        output.close();

        facesContext.responseComplete(); 
    }
	
	    private static String pegarNomeDoArquivo(Part part) {
        for (String header : part.getHeader("content-disposition").split(";")) {
            if (header.trim().startsWith("filename")) {
                String nomeDoArquivo = header.substring(header.indexOf('=') + 1).trim().replace("\"", "");
                return nomeDoArquivo.substring(nomeDoArquivo.lastIndexOf('/') + 1).substring(nomeDoArquivo.lastIndexOf('\\') + 1); // gambi para MSIE, não sei o porque mas já estava assim.  
            }
        }
        return null;
    }
	//GETS E SETS
}

ArquivoRepository.java

public class ArquivoRepository {

    private Manager setManager = new Manager();
    private EntityManager manager = this.setManager.getEntityManager();

    public void adiciona(Arquivo Arquivo) {
        this.manager.persist(Arquivo);
    }

    public Arquivo baixarArquivo(Long id) {
        Query query = this.manager.createQuery("select o.arquivo, o.arquivoNome from Arquivo o WHERE o.id = ?");
        query.setParameter(1, id);
        List results = query.getResultList();
        Iterator it = results.iterator();
        Arquivo arquivo = new Arquivo();
        if (it.hasNext()) {
            Object[] result = (Object[]) it.next();
            byte[] arquivo = (byte[]) result[0];
            String nome = (String) result[1];
            arquivo.setArquivo(arquivo);
            arquivo.setArquivoNome(nome);
        }
        return arquivo;
    }
	//GETS E SETS
}

Manager.java

public class Manager {

    public EntityManager getEntityManager() {
        FacesContext fc = FacesContext.getCurrentInstance();
        ExternalContext ec = fc.getExternalContext();
        HttpServletRequest request = (HttpServletRequest) ec.getRequest();
        EntityManager manager = (EntityManager) request.getAttribute("EntityManager");
        return manager;
    }

    public HttpServletResponse response(FacesContext fc) {
        ExternalContext ec = fc.getExternalContext();
        return (HttpServletResponse) ec.getResponse();
    }
}

edit: criei uma classe apenas para chamar o EntityManager quando precisa-se e o response, para diminuir o numero de linhas.

Parabéns pela iniciativa. Só uma dica, não coloque entitymanager em managed bean. [=

Anotado, pena que é assim que a k-19 ensina na apostila deles.

Anotado, pena que é assim que a k-19 ensina na apostila deles.[/quote]pode ser que a pessoa quis facilitar para quem tá começando, ou ela também nem percebeu. =x

Hebert, qual a melhor pratica para se usar ou pegar o EntityManager? Porque estou chamando ele em todas as ManagedBeans

[quote=MusashiBR]Hebert, qual a melhor pratica para se usar ou pegar o EntityManager? Porque estou chamando ele em todas as ManagedBeans[/quote]ManagedBean não deveria nem saber que um EntityManager está sendo usado.

A única camada a ver um EntityManager seria a camada que faz consulta ao baco de dados. [=

[quote=Hebert Coelho][quote=MusashiBR]Hebert, qual a melhor pratica para se usar ou pegar o EntityManager? Porque estou chamando ele em todas as ManagedBeans[/quote]ManagedBean não deveria nem saber que um EntityManager está sendo usado.

A única camada a ver um EntityManager seria a camada que faz consulta ao baco de dados. [=[/quote]

Esqueci de postar esse filtro que estou usando.

JPAFilter.java

package pacote.filtro;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;


@WebFilter(servletNames = {"Faces Servlet"})
public class JPAFilter implements Filter {

    private EntityManagerFactory factory;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.factory = Persistence.createEntityManagerFactory("PU");
    }

    @Override
    public void destroy() {
        this.factory.close();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        //CHEGADA
        EntityManager manager = this.factory.createEntityManager();
        request.setAttribute("EntityManager", manager);
        manager.getTransaction().begin();
        //CHEGADA

        //FACES SERVLET
        chain.doFilter(request, response);
        //FACES SERVLET

        //SAIDA
        try {
            manager.getTransaction().commit();
        } catch (Exception e) {
            manager.getTransaction().rollback();
        } finally {
            manager.close();
        }
        //SAIDA
    }
}

Editei tentando seguir a dica do Herbert