Upload de arquivos usando Commons-FileUpload

Introdução
Neste tutorial, mostrarei como se faz para enviar arquivos para um servidor através de uma aplicação Web, utilizando o Commons-FileUpload da Jakarta. Serão mostradas duas maneiras de se fazer isso:

1 – Enviar uma imagem para o servidor guardando-a em um campo BLOB do Banco de Dados;

2 – Enviar uma imagem para o servidor, guardá-la em um diretório e armazenar seu endereço no Banco de Dados;

Visão Geral
A API Commons FileUpload tornou fácil e robusta a capacidade de realizar Uploads através de seus Servlets e aplicações Web.

FileUpload analisa gramaticalmente as requisições HTTP conforme RFC 1867 (http://www.ietf.org/rfc/rfc1867.txt) "Form-based File Upload in HTML". Isto quer dizer que, se uma requisição http for submetida usando um método POST, a partir de um formulário tipo "multipart/form-data", então FileUpload pode analisar gramaticalmente esse pedido, e retornar os resultados de maneira fácil para o método que o chamou.

Download do FileUpload 1.1.1

Commons-FileUpload pode ser baixado a partir do endereço:
http://jakarta.apache.org/commons/fileupload/index.html

Após fazer o download e extrair os arquivos, adicione o commons-fileupload-1.1.1.jar ao seu projeto.

Documentação
Neste tutorial procuraremos dar mais atenção à codificação do que à teoria. Uma documentação completa sobre o Commons-FileUpload pode ser encontrada em:
http://jakarta.apache.org/commons/fileupload/using.html

http://jakarta.apache.org/commons/fileupload/apidocs/index.html

e, também no pacote FileUpload 1.1.1.zip

Definindo um formulário para o envio do arquivo
Como exemplo, vamos fazer o upload de uma imagem para o servidor. Um formulário simples deve ser criado em HTML para levar a imagem até nossa aplicação. Este formulário deve obrigatoriamente ser do tipo “multipart/form-data":

<form id="formImagem" name="formImagem" method="post" action="servletupload" enctype="multipart/form-data">

<input type="hidden" id="tipoForm" name="tipoForm" value="imagem">

<input name="imagem" type="file" accept="image/jpeg; image/gif; image/bmp; image/png" id="imagem" class="dados" maxlength="60" tabindex="1" value="c:/" mso-spacerun: yes"> 
width:500px; ">

<input type="submit" id="upload" name="upload" tabindex="2" style="position:absolute; top:20px; left:532px; >

 

</form>

 

Criando o Servlet

Agora vamos criar um Servlet para receber esta requisição:

 

import org.apache.commons.fileupload.servlet.ServletFileUpload;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.FileUpload;

import org.apache.commons.fileupload.FileItemFactory;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileUploadException;

 

public class ServletUpload extends HttpServlet{

 

    //Initialize global variables

    public void init() throws ServletException {

    }

 

    //Process the HTTP Post request

    public void doPost(HttpServletRequest request, HttpServletResponse response)

                       throws ServletException, IOException {

        doGet(request, response);

    }

 

//Process the HTTP Get request

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

            boolean isMultiPart = FileUpload.isMultipartContent(request);

            if (isMultiPart) {

                FileItemFactory factory = new DiskFileItemFactory();

                ServletFileUpload upload = new ServletFileUpload(factory);

                String formulario = "";

                try {

                    List items = upload.parseRequest(request);

                    Iterator iter = items.iterator();

                    while (iter.hasNext()) {

                        FileItem item = (FileItem) iter.next();

                        if (item.getFieldName().equals("tipoForm")) {

                            formulario = item.getString();

                        }

                        if (!item.isFormField()) {

                            if (item.getName().length() > 0) {

                                this.inserirImagem(item);

                            }

                        }

                    }

                }

catch (FileUploadException ex) {

   ex.printStackTrace();

                }

catch (Exception ex) {

   ex.printStackTrace();

                }

            }

    }

   // implementação de demais métodos do Servlet.

}

 

Inserindo e recuperando a Imagem em um Campo Blob

Se você analisou o código do Servlet acima, deve ter notado a chamada ao método inserirImagem(item) que ainda não foi implementado. Pois bem, iremos agora escrever este método que irá inserir a imagem em um campo Blob do banco de dados. Para este exemplo eu usei o MySql.

 

A estrutura e criação da tabela deste exemplo são:

 

TabelaTeste

Codigo (Integer)

Imagem (Blob)

 

CREATE TABLE TabelaTeste (

      codigo                  INT UNSIGNED NOT NULL,

      imagem            BLOB NOT NULL

);

 

A seguir a implementação do método inserirImagem(FileItem item):

 

     /**

     * @param item FileItem, representa um arquivo que é enviado pelo formulario

     * MultiPart/Form-data

     * @throws IOException

     * @throws ServletException

     */

    private  void inserirImagem(FileItem item) {

     

Connection conexao = null;

 

/**

 

  Estabeleça a conexão

 

*/

 

      PreparedStatement declaracao = null;

 

            String sql = "INSERT INTO TabelaTeste (codigo, imagem) VALUES(?, ?)

                         ";

 

try {

                  declaracao = conexao.prepareStatement(sql);

            declaracao.setInt(1, 1); // codigo 1

                 declaracao.setBinaryStream(2, item.getInputStream(),

                                           (int) item.getSize() );

                  declaracao.executeUpdate();

 

             } catch (SQLException ex) {

                        ex.printStackTrace();

            } catch (Exception ex) {

                  ex.printStackTrace();

            }

}

 

A seguir, o método recuperaImagem() mostra como fazer para recuperar esta imagem que foi inserida no Banco de Dados.

 

OBS: importar a classe com.mysql.jdbc.Blob

 

public ImageIcon recuperaImagem() {

 

Connection conexao = null;

 

/**

 

  Estabeleça a conexao

 

*/

 

        Statement declaracao = null;

        ResultSet resultado = null;

        StringBuffer sql = new StringBuffer();

        sql.append("SELECT imagem FROM tabelaTeste WHERE codigo = 1");

        ImageIcon imagem = null;

        try {

            declaracao = conexao.createStatement();

            resultado = declaracao.executeQuery(sql.toString());

 

            if (resultado.next()) {

                Blob blob = (Blob) resultado.getBlob("imagem");

                if (blob!=null){

                    imagem = new ImageIcon(blob.getBytes(1,

                                                        (int) blob.length()));

                }

            }

        } catch (SQLException ex) {

            ex.printStackTrace();

        } catch (Exception ex) {

            ex.printStackTrace();

        }

        return imagem;

    }

 

Gravando e recuperando a Imagem em um diretório do servidor

Os Exemplos acima mostraram como podemos fazer, de maneira bem simples, a inserção e a recuperação de uma imagem para um campo blob do banco de dados.

 

Agora mostraremos uma outra forma de se fazer este upload, porém, vamos gravar a imagem em um diretório do servidor e no banco de dados guardaremos apenas o endereço desta imagem.

 

Usaremos exatamente o mesmo formulário criado (html) e o mesmo método doGet() do Servlet mostrado acima. A única diferença será a chamada ao método que ao invés de ser:
 this.inserirImagem(item);

Será

 this.inserirImagemDiretorio(item);

 

Para isto vamos criar uma outra tabela no Banco de Dados conforme a estrutura a seguir:

 

TabelaTeste2

Codigo (Integer)

Imagem (Varchar)

 

CREATE TABLE TabelaTeste2 (

      codigo                  INT UNSIGNED NOT NULL,

      imagem            VARCHAR (255)

);

 

Agora vamos escrever o método inserirImagemDiretorio(FileItem item) que irá realizar duas tarefas:

 

1 – Guardar a imagem em um diretório do servidor;

2 – Guardar no Banco de dados o endereço para recuperação desta imagem;

 

     /**

     *

     * @param item FileItem, representa um arquivo que é enviado pelo formulario

     * MultiPart/Form-data

     * @throws IOException

     */

    private void inserirImagemDiretorio(FileItem item) throws

                                                         IOException {

 

            //Pega o diretório /logo dentro do diretório atual de onde a

            //aplicação está rodando

            String caminho = getServletContext().getRealPath("/logo")

                             + "/";

     

             // Cria o diretório caso ele não exista

            File diretorio = new File(caminho);

            if (!diretorio.exists()){

                diretorio.mkdir();

            }

 

            // Mandar o arquivo para o diretório informado

            String nome = item.getName();

            String arq[] = nome.split("\\\\");

            for (int i = 0; i < arq.length; i++) {

                nome = arq[i];

            }

 

            File file = new File(diretorio, nome);

            FileOutputStream output = new FileOutputStream(file);

            InputStream is = item.getInputStream();

            byte[] buffer = new byte[2048];

            int nLidos;

            while ((nLidos = is.read(buffer)) >= 0) {

                output.write(buffer, 0, nLidos);

            }

            output.flush();

            output.close();

 

 

//Guarda no banco de dados o endereço para recuperação da imagem

 

Connection conexao = null;

 

/**

 

  Estabeleça a conexão

 

*/

 

      PreparedStatement declaracao = null;

 

            String sql = "INSERT INTO TabelaTeste2 (codigo, imagem) VALUES(?, ?)

                         ";

 

try {

                  declaracao = conexao.prepareStatement(sql);

            declaracao.setInt(1, 1); // codigo 1

                 declaracao.setString(2, caminho);

                   resultado = declaracao.executeUpdate();

             } catch (SQLException sqlEx) {

                        ex.printStackTrace();

            } catch (Exception ex) {

                  ex.printStackTrace();

            }

    }

 

Escrevendo o método recuperarImagemDiretorio():

 

public ImageIcon recuperaImagemDiretorio() {

 

Connection conexao = null;

 

/**

 

  Estabeleça a conexao

 

*/

 

        Statement declaracao = null;

        ResultSet resultado = null;

        StringBuffer sql = new StringBuffer();

        sql.append("SELECT imagem FROM tabelaTeste2 WHERE codigo = 1");

        ImageIcon imagem = null;

        try {

            declaracao = conexao.createStatement();

            resultado = declaracao.executeQuery(sql.toString());

            if (resultado.next()) {

 

String caminhoImagem = resultado.getString("imagem");

 

                if (caminhoImagem!=null){

                    imagem = new ImageIcon(caminhoImagem);

                } 

          }

        } catch (SQLException ex) {

            ex.printStackTrace();

        } catch (Exception ex) {

            ex.printStackTrace();

        }

        return imagem;

    }

 

Conclusão

Vimos como pode ser fácil realizar UpLoads de imagem para um servidor, seja para um campo Blob ou para um diretório qualquer também no servidor.

 

A utilização de qualquer um desses métodos vai depender de suas decisões de projeto analisando qual será a melhor e mais viável alternativa.

 

A recuperação destas imagens pode ser utilizada, por exemplo para exibições em relatórios (conforme mostrei em artigos anteriores), exibição de paginas personalizadas de usuários do sistema, dentre outras.

 

Espero que todos tenham gostado deste tutorial e tirado o maior proveito dele.

 

Um abraço.

Até a próxima!