Arquivo

Posts Tagged ‘recortar imagem’

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