quarta-feira, 4 de janeiro de 2012

Upload de Arquivo com JSF + Primefaces (já vem no Netbeans 7)



Pré-condição: projeto web criado com os frameworks (JSF e Primefaces)

Primeiramente vamos precisar de duas bibliotecas extras, faça o download:




1) Após baixar os arquivos, adicione as depedências ao seu projeto.

2) Configure o arquivo web.xml adicionando o filter do fileUpload.

<filter>
       <filter-name>PrimeFaces FileUpload Filter</filter-name>
  
<filter-class> org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>

   <filter-mapping>
       <filter-name>PrimeFaces FileUpload Filter</filter-name>
       <servlet-name>Faces Servlet</servlet-name>
   </filter-mapping>  

3) Agora crie um ManagedBean ou utilize um outro qualquer e adicione:

public void fileUploadAction(FileUploadEvent event) {
       try {
           ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
           HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

           FacesContext aFacesContext = FacesContext.getCurrentInstance();
           ServletContext context = (ServletContext) aFacesContext.getExternalContext().getContext();
          
           String realPath = context.getRealPath("/");

// Aqui cria o diretorio caso não exista
           File file = new File(realPath + "/fotos/");
           file.mkdirs();
           
           byte[] arquivo = event.getFile().getContents();
           String caminho = realPath + "/fotos/" + event.getFile().getFileName();    
     
// esse trecho grava o arquivo no diretório
           FileOutputStream fos = new FileOutputStream(caminho);
           fos.write(arquivo);
           fos.close();
           

       } catch (Exception ex) {
           System.out.println("Erro no upload de imagem" + ex);
       }
   }


4) Na página adicione a chamada ao componente de upload do primefaces

<p:fileUpload id="upload" update="foto" fileUploadListener="#{uploadMB.fileUploadAction}" auto="true"/>

Lembrando que é necessário ter declarado o xmlns:p="http://primefaces.prime.com.tr/ui" para usar o primefaces

Agora é só testar.
Para verificar se o arquivo foi salvo corretamente, acesse a pasta build do seu projeto e veja se dentro de web/fotos esta o seu arquivo.

18 comentários:

  1. Ola quando eu no meu projeto está dando um erro no filter do fileUpload, web.xhtml esse é o erro:

    Caused by: java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactory
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2308)
    at java.lang.Class.getDeclaredFields(Class.java:1760)
    at org.apache.catalina.startup.WebAnnotationSet.getDeclaredFields(WebAnnotationSet.java:452)
    at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:257)
    at org.apache.catalina.startup.WebAnnotationSet.loadApplicationFilterAnnotations(WebAnnotationSet.java:107)
    at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:65)
    at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:381)
    at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:858)
    at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:345)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 40 more
    Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileItemFactory
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)

    por que será?

    ResponderExcluir
  2. Olá, gostei muito do seu blog! Ainda não testei seu exemplo mais vou testar e depois comento.

    camillotargas@hotmail.com

    ResponderExcluir
  3. Legal, sabe como fazer o Download desse arquivo que subiu para o upload?
    sem usar banco

    ResponderExcluir
  4. boa noite e parabens pelo post, por favor tem como vc me mandar o projeto completo, isso é se vc tiver é claro pois no meu tcc estou usando upload e primefaces seria de uma ahuda q vc nem imagina, pois ja procurei não consegui achar um que eu pudesse entender pelo menos um pouco desde já obrigado.
    andreluizsousa@terra.com.br

    ResponderExcluir
  5. bem legal seu post, mas queria dar uma dica:

    Voê não acha que nesse trecho do MB existem 2 objetos desnecessarios ?

    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); // esse
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

    FacesContext aFacesContext = FacesContext.getCurrentInstance(); //e esse
    ServletContext context = (ServletContext) aFacesContext.getExternalContext().getContext();

    Você deveria fazer assim, na minha opnião:

    HttpServletResponse response = (HttpServletResponse) FacesContext
    .getCurrentInstance()
    .getExternalContext()
    .getResponse();

    ServletContext context = (HttpServletResponse) FacesContext
    .getCurrentInstance()
    .getExternalContext()
    .getContext();

    fica com 2 objetos a menos e o codigo fica mais limpo e elegante.

    ResponderExcluir
  6. Ola tudo bem?
    Me desculpe a falta de conhecimento mas quando eu chamo o metodo ele pede para passar o event, e não reconhece o metodo se não chama-lo assim fileUploadListener="#{projetoBean.fileUploadAction(event)}" o que devo mudar para que não precise passar o event?

    ResponderExcluir
  7. Olá boa noite,

    sempre vejo códigos de upload com a pasta de destino desta forma como vc colocou

    File file = new File(realPath + "/fotos/");

    ou seja lá no servidor remoto a foto vai estar dentro de sua_app/fotos, acontece que normalmente vc hospeda sua aplicação em um server remoto e faz upload do war via ftp, dessa forma como está implementado,toda vez que der deploy na aplicação vc vai sobrescrever a pasta fotos e toda informação já enviada vai ser perdida,o que é inviavel pra um sistema em produção, qual a melhor solução a adotar em sua opinião?

    ResponderExcluir
    Respostas
    1. isso resolve seu problema de criação de diretorio:
      File file = new File(realPath);
      if(!file.exists())
      file.mkdirs();

      Excluir
  8. Muito obrigado pelo Tutorial! Funcionou perfeitamente! :D

    ResponderExcluir
  9. Ate que enfim, apareceu alguem que resolvesse o meu problema.... Parabens pelo tutorial! Funcionou perfeitamente... Obrigado!

    ResponderExcluir
  10. Olha quando vou a pasta nao tem la o ficheiro. como resolver??

    ResponderExcluir
  11. //usei este metodo em um dos meus controlles...

    public void fileUploadAction(FileUploadEvent event) {
    try {
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

    FacesContext aFacesContext = FacesContext.getCurrentInstance();
    ServletContext context = (ServletContext) aFacesContext.getExternalContext().getContext();

    String realPath = context.getRealPath("/");

    // Aqui cria o diretorio caso não exista
    File file = new File(realPath + "/doc/");
    file.mkdirs();

    byte[] arquivo = event.getFile().getContents();
    String caminho = realPath + "/doc/" + event.getFile().getFileName();

    // esse trecho grava o arquivo no diretório
    FileOutputStream fos = new FileOutputStream(caminho);
    fos.write(arquivo);
    fos.close();


    } catch (Exception ex) {
    System.out.println("Erro no upload de imagem" + ex);
    }
    }

    // e melhorei este no xhtml




    // mas ao fazer upload nao aperece o file na pasta... Ajuda

    ResponderExcluir
  12. Parabéns pelo Post, foi o único que testei e realmente deu certo, tentei de várias formas possíveis e não tinha conseguido até agora, porém agora tem uma forma de pegar essa foto para mostrar em um xhtml?

    ResponderExcluir
  13. Parabéns pelo post me ajudou bastente.

    ResponderExcluir