Arquivo

Posts Tagged ‘p:fileupload’

Resolvendo problema com ACENTUAÇÃO no nome do ARQUIVO com FILEUPLOAD do PRIMEFACES

Nesta última semana tive uns probleminhas com o FileUpload ao pegar o nome do arquivo que estava realizando um upload, os nome dos arquivos que possuiam acentuação sempre vinham com estes caracteres trocados por caracteres especiais. O cliente não ficou satisfeito, pois se eu fizesse o upload de uma arquivo DECLARAÇÃO_IMPOSTO_RENDA_20011.PDF vinha algo assim DECLARA≤Â÷ÆO_IMPOSTO_RENDA_2011.PDF.

Após várias tentativas consegui uma resolução para o problema de forma fácil e elegante. Para resolver, basta criarmos um filtro para setar o tipo de codificação do texto contido na resposta e na requisição.

Vamos por a mão na massa! Crie um pacore filters no seu projeto e dentro dele crie uma classe CharacterEncodingFilter.java. Abaixo o exemplo do código desta classe:

public class CharacterEncodingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

Bem simple, apenas setamos a codificação na resposta e na requisição. Além disso precisamos declarar este filtro no web.xml:

    <filter>
        <filter-name>Character Encoding Filter</filter-name>
        <filter-class>br.com.tecnodocs.vdocs.filters.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Character Encoding Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>

Com isso você conseguirá pegar os nomes dos arquivos através do p:fileUpload em qualquer SO sem problemas de acentuação.

Espero que a dica ajude outros da mesma forma que me ajudou, abraço!

Benigno M. Sales

“Ame seus inimigos, faça o bem para aqueles que te odeiam, abençoe aqueles que te amaldiçoam, reze por aqueles que te maltratam. Se alguém te bater no rosto, ofereça a outra face. “
( Jesus Cristo )

JSF 2.0 – Primefaces 2.2 – FileUpload com ImageCropper

 

FileUpload

O componente FileUpload, como o prórprio nome diz, é responsável pelo envio de imagens da máquina cliente para o lado servidor. Este componente vai além da navegação da tag html <input type=”file”>, trazendo funcionalidades flashjavascript. Podemos filtrar arquivos, fazer múltiplos uploads, processamento parcial da página e uma barra para acompanhamento do progresso do upload. Caso o navegador cliente não suporte flash ou javascrip o fileupload retorna a funcionalidade padrão de <input type=”file”>.

Em um post anterior, já descrevi como utilizar FileUpload, porém, da versão utilizada no post até a atual tivemos algumas modificações na forma de configuração, o que me leva a descrever alguns procedimentos novamente.

Bibliotecas necessárias:

Configuração do web.xml:

<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>

Abaixo descrição dos principais atributos do componente:

  • id:  Identificador único do componente
  • rendered: Valor boleano para especificar se o componente deve ou não ser exibido
  • fileUploadListener:  Método a ser executado quando sempre que um arquivo for ser enviado
  • multiple:  Habilita o envio de múltiplos arquivos
  • update: id de um componente a ser atualizado após o término do envio do arquivo
  • auto: Quando habilitado(true) o upload do arquivo começa logo após a seleção
  • label: Rótulo do botão, o padrão é ‘Browse’
  • image: Imagem de fundo do botão
  • cancelImage: Imagem do botão cancelar
  • width: Largura do botão de procura
  • height: Altura do botão de procura
  • allowTypes: Lista de extensões de arquivos aceitas
  • description: Rótulo que descreve quais tipos de arquivo podem ser enviados
  • sizeLimit: Número máximo de bytes aceitos
  • wmode: Propriedade wmode do objeto flash
  • customUI: Quando habilitado(true) os links upload e cancel  não são exibidos
  • widgetVar: Nome do widget para referências em javascript

ImageCropper

O componente ImageCropper  tem como funcionalidade recortar determinadas regiões de uma imagem. Esta funcionalidade criauma nova imagem contendo a região recordada e associando-a a um objeto do tipo CroppedImage instanciado no lado servidor.

Abaixo descrição dos principais atributos do componente:

  • id:  Identificador único do componente
  • rendered: Valor boleano para especificar se o componente deve ou não ser exibido
  • required: Indica se o campo é obrigatório
  • value:  EL para um Objeto do tipo CroppedImage instanciado no managed bean.
  • image:  Caminho para a imagem(context path)
  • initialCoords:  Coordenadas da posição inicial da região de corte

Criação de Aplicação integrando FileUpload e ImageCropper

Para criação desta aplicação iremos criar uma view(index.xhtml), uma pasta imagens onde armazenaremos as imagens utilizadas no sistema e uma pasta upload para colocar as imagens enviadas através do file upload. A estrutura do projeto ficará conforme imagem abaixo:

Para este projeto simples devemos criar um bean gerenciado de escopo de sessão para controlar a nossa view, abaixo confira o código.
Obs.: Desconsideramos os getters e setters.

IndexManagedBean.java

@ManagedBean
@SessionScoped
public class IndexManagedBean {

private StreamedContent imagemEnviada = new DefaultStreamedContent();
private String imagemTemporaria;
private CroppedImage croppedImage;
private boolean exibeBotao = false;

/* getters e setters */

   public void criaArquivo(byte[] bytes, String arquivo) {
      FileOutputStream fos;
      try {
         fos = new FileOutputStream(arquivo);
         fos.write(bytes);
         fos.close();
      } catch (FileNotFoundException ex) {
         Logger.getLogger(IndexManagedBean.class.getName()).log(Level.SEVERE, null, ex);
      } catch (IOException ex) {
         Logger.getLogger(IndexManagedBean.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

   public void enviarImagem(FileUploadEvent event) {
      byte[] img = event.getFile().getContents();
      imagemTemporaria = event.getFile().getFileName();
      FacesContext facesContext = FacesContext.getCurrentInstance();
      ServletContext scontext = (ServletContext) facesContext.getExternalContext().getContext();
      String arquivo = scontext.getRealPath("/upload/" + imagemTemporaria);
      criaArquivo(img, arquivo);
      setExibeBotao(true);
   }

   public void crop() {
      setImagemEnviada(new DefaultStreamedContent(new ByteArrayInputStream(croppedImage.getBytes())));
   }
}

O método enviarImagem(FileUploadEvent event) é utilizado no atributo fileUploadListener para ser executado sempre que uma imagem estiver sendo enviada. É neste método onde poderemos fazer conversões, criação de arquivos, etc.

Observem que no método é passado um parâmetro event com o qual eu consigo retirar todos os dados que preciso, como nome de arquivo, caminho, array de bytes referentes ao arquivo, etc. Iremos criar um arquivo temporário que será utilizado na view com o imageCropper, este arquivo é criado na pasta upload através do método criaArquivo, e também salvar o nome do arquivo criado em uma String, a imagemTemporaria.

Em seguida criamos o método crop() para coletar a imagem recortada e jogar dentro da imagemEnviada que é do tipo StreamedContent, que pode ser trabalhado dinamicamente com o um p:graphicImage. Abaixo confira a utilização de todos os métodos e atributos na view:

<h:form>
   <p:panel header="ImageCropper com FileUpload - QuebrandoParadigmas.com" style="width: 900px; margin: 0 auto; margin-top: 0px">
      <p:fileUpload fileUploadListener="#{indexManagedBean.enviarImagem}" sizeLimit="204800" auto="true"
                            image="/imagens/imgBuscar.png" customUI="true" update="outputPanelUpload"/>
      <p:outputPanel id="outputPanelUpload">
         <h:panelGrid columns="2">
            <h:outputText value="Imagem" rendered="#{indexManagedBean.exibeBotao}"/>
             <h:outputText value="Pre-visualização" rendered="#{indexManagedBean.exibeBotao}"/>
             <p:imageCropper id="imageCropperImagemTemporaria" value="#{indexManagedBean.croppedImage}"
              image="#{pageContext.servletContext.contextPath}/upload/#{indexManagedBean.imagemTemporaria}"/>
              <p:graphicImage value="#{indexManagedBean.imagemEnviada}" cache="false"/>
         </h:panelGrid>
         <p:commandLink action="#{indexManagedBean.crop}" update="outputPanelUpload"
                                   rendered="#{indexManagedBean.exibeBotao}">
            <p:graphicImage style="margin-top: 5px; border: none;" value="/imagens/imgCortar.png"/>
         </p:commandLink>
      </p:outputPanel>
   </p:panel>
</h:form>

Criamos um outputPanel de nome outputPanelUpload que é  atualizado sempre que algum dado no managed bean é alterado, como quando a imagem de upload é enviada e damos um update para exibi-la ou quando cortamos a imagem e atualizamos para exibir a região cortada em uma outra imagem. Gostaria de salientar o código abaixo, pois é nele onde carregamos  a imagem que foi criada no na pasta upload do servidor:
image=”#{pageContext.servletContext.contextPath}/upload/#{indexManagedBean.imagemTemporaria}”

Perceba que pego o caminho do contexto(pasta web) e dentro dele a pasta upload e, em seguida, acrescento com uma EL que representa o nome do arquivo que foi definido no fileUploadListener(enviaImagem).

O resultado você pode conferir no vídeo abaixo:





Twitter: @benignoms

JSF 2.0 – PrimeFaces – CRUD com Foto utilizando p:fileUpload

Olá pessoal,

Neste post resolvi fazer um CRUD completo, incluindo um campo imagem que será salvo na base de dados. Para aqueles que queiram utilizar campos de imagem no Mysql utilizando JSF, este post é perfeito.

Então, vamos por a mão na massa. Nesta publicação irei utilizar:

– commons-io-2.0.jar
– commons-fileupload-1.2.2.jar
– primefaces-2.2.RC1.jar
– Mojarra 2.0.3

As duas primeiras bibliotecas são exigências do componente p:fileUpload do primefaces. Além disso, devemos fazer uma breve configuração no web.xml para que o componente funcione adequadamente.

</pre>
<code> <filter>
 PrimeFaces FileUpload Filter
 <filter-class>
 org.primefaces.webapp.filter.FileUploadFilter
 </filter-class>
 </filter>
 <filter-mapping>
 PrimeFaces FileUpload Filter
 <servlet-name>Faces Servlet</servlet-name>
 </filter-mapping></code>

<code>


Obs.: Neste exemplo não irei explicar detalhes do componente FileUpload, esta não é a intensão deste post, e sim mostrar um crud completo usando JSF 2.0, primefaces e o componente. Caso você deseje saber mais sobre este componente clique aqui.

Bom, no nosso exemplo utilizamos MySQL, um esquema de nome test e uma tabela jogadores com a estrutura demonstrada na imagem abaixo:

Povoado com os seguintes dados:

A estrutura de pacotes do nosso sistema contemplará um modelo(bean), um dao, um controller(managed bean), uma factory de conexões e uma classe Utils. Veja imagem abaixo:

Nosso modelo Jogador.java irá espelhar a tabela Jogadores com todos os atributos e seus getters e setters . Daremos destaque ao campo da foto que será do tipo byte[]. Veja abaixo o código do modelo:

</pre>
<code>public class Jogador {</code>

private int id;
 private String nome;
 private int estado;
 private String descricao;
 private byte[] foto;

public String getDescricao() {
 return descricao;
 }

public void setDescricao(String descricao) {
 this.descricao = descricao;
 }

public int getEstado() {
 return estado;
 }

public void setEstado(int estado) {
 this.estado = estado;
 }

public byte[] getFoto() {
 return foto;
 }

public void setFoto(byte[] foto) {
 this.foto = foto;
 }

public int getId() {
 return id;
 }

public void setId(int id) {
 this.id = id;
 }

public String getNome() {
 return nome;
 }

public void setNome(String nome) {
 this.nome = nome;
 }
 }
 

No DAO irei explicar dois métodos o de listarTodos e o de salvar, o método excluir fica como tarefa de casa :D. No método listarTodos iremos selecionar todos os registros da tabela jogadores e retornar em uma coleção List, já no método salvar passamos um objeto Jogador como parâmetro e utilizamos este objeto para preencher os parâmetros do prepared statement. Segue abaixo o código do DAO:

</pre>
 <code>public class JogadorDAO {</code>

private Connection con;
 private String sql;
 private final String COL_ID = "id";
 private final String COL_NOME = "nome";
 private final String COL_ESTADO = "estado";
 private final String COL_DESCRICAO = "descricao";
 private final String COL_FOTO = "foto";

public List listaTodos() {
 List jogadores = new ArrayList();
 con = ConnectionFactory.getConnection();
 sql = "select * from jogadores j";
 try {
 PreparedStatement ps = con.prepareStatement(sql);
 ResultSet rs = ps.executeQuery();
 while (rs.next()) {
 Jogador j = new Jogador();
 j.setId(rs.getInt(COL_ID));
 j.setNome(rs.getString(COL_NOME));
 j.setEstado(rs.getInt(COL_ESTADO));
 j.setDescricao(rs.getString(COL_DESCRICAO));
 j.setFoto(rs.getBytes(COL_FOTO));
 jogadores.add(j);
 }
 con.close();
 } catch (SQLException ex) {
 Logger.getLogger(JogadorDAO.class.getName()).log(Level.SEVERE, null, ex);
 }
 return jogadores;
 }

public void salva(Jogador jogador) {
 con = ConnectionFactory.getConnection();
 if (jogador.getId() == 0) {
 sql = "insert into jogadores(nome,estado,foto,descricao) values(?,?,?,?)";
 } else {
 sql = "update jogadores set nome = ?,estado = ?,foto = ?,descricao=? where id=?";
 }
 try {
 PreparedStatement ps = con.prepareStatement(sql);
 ps.setString(1, jogador.getNome());
 ps.setInt(2, jogador.getEstado());
 ps.setBytes(3, jogador.getFoto());
 ps.setString(4, jogador.getDescricao());
 if(jogador.getId() != 0) {
 ps.setInt(5, jogador.getId());
 }
 ps.execute();
 con.close();
 }
 catch (SQLException ex) {
 Logger.getLogger(JogadorDAO.class.getName()).log(Level.SEVERE, null, ex);
 }
 }
 }

Abaixo o nosso Controller(Managed Bean) JogadorController.java:

</pre>
<code>@ManagedBean
 @SessionScoped
 public class JogadorController {</code>

private Jogador jogador = new Jogador();
 private Jogador jogadorSelecionado = new Jogador();
 private JogadorDAO dao = new JogadorDAO();
 private List<Jogador> jogadores = new ArrayList<Jogador>();
 private StreamedContent imagem;

public Jogador getJogadorSelecionado() {
 return jogadorSelecionado;
 }

public void setJogadorSelecionado(Jogador jogadorSelecionado) {
 this.jogadorSelecionado = jogadorSelecionado;
 }

public Jogador getJogador() {
 return jogador;
 }

public void setJogador(Jogador jogador) {
 this.jogador = jogador;
 }

public List<Jogador> getJogadores() {
 return jogadores;
 }

public void setJogadores(List<Jogador> jogadores) {
 this.jogadores = jogadores;
 }

public StreamedContent getImagem() {
 return imagem;
 }

public void setImagem(StreamedContent imagem) {
 this.imagem = imagem;
 }

public void handleFileUpload(FileUploadEvent event) {
 try {
 imagem = new DefaultStreamedContent(event.getFile().getInputstream());
 byte[] foto = event.getFile().getContents();
 this.jogador.setFoto(foto);
 } catch (IOException ex) {
 Logger.getLogger(JogadorController.class.getName()).log(Level.SEVERE, null, ex);
 }
 }

public void salva() {
 dao.salva(jogador);
 jogadores = dao.listaTodos();
 Utils.showFacesMessage("Dados salvos com SUCESSO", 2);
 }

public void novo() {
 jogador = new Jogador();
 imagem = new DefaultStreamedContent();
 }

public void mudaJogador() {
 jogador.setId(jogadorSelecionado.getId());
 jogador.setNome(jogadorSelecionado.getNome());
 jogador.setDescricao(jogadorSelecionado.getDescricao());
 jogador.setFoto(jogadorSelecionado.getFoto());
 imagem = new DefaultStreamedContent(new ByteArrayInputStream(jogador.getFoto()));
 }

public void buscaJogador() {

}

public void limpaImagem() {
 this.imagem = new DefaultStreamedContent();
 }

public JogadorController() {
 jogadores = dao.listaTodos();
 }

Vale a pena destacar esta classe. Nela teremos dois objetos Jogador, uma coleção List<Jogador>, um dao JogadorDAO e um atributo imagem do tipo StreamedContent. Este último atributo é de um tipo que o componente p:graphicImage consegue fazer um binding com o nosso controller. Sim, mas e ai? Como vou preencher esse objeto. Calma garotinho! Vamos fazer como o Jack, vamos por partes.  Nesta mesma classe temos todos os metodos getters e setters dos atributos, menos do DAO. Temos tambem um método que vale ressaltar que é o handleFileUpload que é responsável por pegar a imagem que será “upada” pelo p:fileupload e salvar em um atributo, no nosso caso, imagem. Além disso, eu aproveito e ja preencho o campo foto byte[] que será salvo no banco pelo dao. Observe que o campo imagem será utilizado somente como um atributo temporário para exibir a imagem que foi enviada através do p:fileupload. Abaixo observe como ficou a nossa view:

cadastro.xhtml


<code><html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:p="http://primefaces.prime.com.tr/ui"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core">
 <h:head>
 <title>Exemplo Cadastro FOTO - Primefaces</title>
 <link href="#{facesContext.externalContext.requestContextPath}/css/custom-theme/skin.css" rel="stylesheet" type="text/css" />
 </h:head>
 <p:dialog id="janela" widgetVar="janela" width="450" position="top" modal="true">
 <p:outputPanel id="painel">
 <h:form id="formulario">
 <p:messages id="mensagens"/>
 <h:panelGrid columns="2">
 <h:outputText value="Nome"/>
 <h:inputText value="#{jogadorController.jogador.nome}" style="width: 300px"/>
 <h:outputText value="Descrição"/>
 <h:inputTextarea rows="6" value="#{jogadorController.jogador.descricao}" style="width: 300px"/>
 <h:outputText value="Foto"/>
 <p:graphicImage value="#{jogadorController.imagem}" id="imagem" cache="false"/>
 <h:column/>
 <h:column>
 <p:fileUpload  sizeLimit="204800" auto="true" widgetVar="uploader" label="Procurar..."  fileUploadListener="#{jogadorController.handleFileUpload}"
 allowTypes="*.jpg;*.png;*.gif;" description="Images" update="imagem" multiple="false" customUI="true"/>
 </h:column>
 </h:panelGrid>
 <h:panelGrid columns="3">
 <p:commandButton image="ui-icon-disk" value="Salvar" action="#{jogadorController.salva}" ajax="true" update="listaJogadores mensagens"/>
 </h:panelGrid>
 </h:form>
 </p:outputPanel>
 </p:dialog>
 <p:outputPanel id="listaJogadores">
 <h:form>
 <p:panel header="Lista de Jogadores" style="width: 450px;">
 <p:commandButton image="ui-icon-circle-plus" value="Novo" action="#{jogadorController.novo}" ajax="true" update="painel" oncomplete="janela.show()"/>
 <br></br><br></br>
 <p:dataTable emptyMessage="Nenhum jogador localizado." value="#{jogadorController.jogadores}" var="jogador" selectionMode="single" paginator="true" rows="6" dynamic="true">
 <p:column headerText="Nome">
 <h:outputText value="#{jogador.nome}"/>
 </p:column>
 <p:column style="width: 60px">
 <p:commandButton image="ui-icon-search" action="#{jogadorController.mudaJogador}" update="painel" ajax="true" immediate="true" oncomplete="janela.show()">
 <f:setPropertyActionListener value="#{jogador}" target="#{jogadorController.jogadorSelecionado}"/>
 </p:commandButton>
 <p:commandButton image="ui-icon-circle-close" action="#{jogadorController.mudaJogador}" update="painel" ajax="true" immediate="true" oncomplete="janela.show()">
 <f:setPropertyActionListener value="#{jogador}" target="#{jogadorController.jogadorSelecionado}"/>
 </p:commandButton>
 </p:column>
 </p:dataTable>
 </p:panel>
 </h:form>
 </p:outputPanel>
 </html></code>

Irei dar ênfase ao componente p:fileUpload.

Atributo sileLimit indicando o tamanho máximo da imagem, auto=true indica que assim que a imagem for selecionada será feito o upload automaticamente, o fileUploadListener chama o método que manipulará o FileUploadEvent, allotypes indica as extensões de arquivos permitidos e o atributo update indica o id do campo a ser atualizado quando o upload terminar.   Bom, é isso. Este foi um post rápido pois estou com pouco tempo, mas qualquer dúvida entrem em contato por comentários.  Abaixo seguem as imagens do nosso exemplo:



Espero ter ajudado, e qualquer dúvida mandem um comentário! Abraço a todos!