Em versões mais antigas do Servlet tínhamos que apelar para APIs externas para realizar o upload de arquivos no java, agora com Servlet 3 o trabalho ficou mais fácil.

Para começar vamos ao formulário, não esquecendo do enctype="multipart/form-data" para o arquivo ser enviado junto com a requisição.

<form method="POST" action="/upload/UploadServlet" enctype="multipart/form-data">
     
    <div class="input">
        <label>Upload</label>
        <input type="file" name="arquivo">
    </div>
     
    <input type="submit" value="Enviar">
</form>

MultipartConfig Annotation

Par a lidar com requisições multipart/form-data devemos anotar o Servlet com a anotação @MultipartConfig e configurar seus atributos com as configurações de upload.

  • MaxFileSize: Especifica o tamanho máximo de cada arquivo que será aceito. O tamanho é especificado em bits, então 1024 * 1024 * 5 = 10MB.
  • location: O diretório temporário em que os arquivos enviados serão armazenados para processamento. O valor padrão é “”.
  • maxRequestSize: Especifica o tamanho total máximo permitido da requisição multipart/form-data. O valor padrão é -1L que seria ilimitado.
  • fileSizeThreshold: Se o tamanho de um arquivo for superior a este limite ele será gravado em disco, em vez de guardar na memória;
@WebServlet("/UploadServlet")
@MultipartConfig(
        fileSizeThreshold = 1024 * 1024, // 1MB
        maxFileSize = 1024 * 1024 * 4,   // 4MB
        maxRequestSize = 1024 * 1024 * 4 // 4MB
)
public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
 
    public UploadServlet() {
        // TODO Auto-generated constructor stub
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         
        //aqui manipulamos o arquivo recebido 
    }
 
}

Para pegarmos os arquivos envidados pelo formulário utilizamos os métodos request.getParts() que retorna uma Collection de Part com todos os arquivos envidados pelo formulário ou request.getPart(String name) que retorna o Part do arquivo enviado com o name passado por parâmetro.

A classe Part representa o arquivo enviado pela requisição e possui os seguintes métodos:

  • getName(): Retorna o name do campo input do formulário em que foi envidado o arquivo.
  • getSize(): Retorna o tamanho do arquivo em bytes.
  • getContentType(): Retorna o tipo do arquivo enviado. Ex.: application/pdf, image/png, text/plain.
  • getHeaderNames(): Retorna uma Collection com todos os nomes dos header da Part
  • getHeader( String name ) Dado o nome de um header retorna o valor do header. Ex.: getHeader(“content-disposition”) retorna “form-data; name=”arquivo”; filename=”documento.pdf”.
  • getInputStream(): Retorna um InputStream para leitura do arquivo enviado.
  • write( String fileName ): Grava o arquivo enviado no local passado por parâmetro.

Se você deve ter notado diferente de outras linguagem não temos um método direto para pegar o nome do arquivo, mas o nome do arquivo está no headercontent-disposition“, então podemos quebrar esta String para pegar o nome do arquivo, vamos ao método que dado um Part retorna o nome do arquivo.

public String getFileName(Part part){
    String header = part.getHeader( "content-disposition" );
    for( String tmp : header.split(";") ){
        if( tmp.trim().startsWith("filename") ){
            return tmp.substring( tmp.indexOf("=")+2 , tmp.length()-1 );
        }
    }
    return null;
}

Agora um exemplo do método doPost.

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         
    File dir = new File( getServletContext().getRealPath("uploads") );// diretório de upload
         
    //se o diretório não existe ele cria
    if( !dir.isDirectory() ){
        dir.mkdir();
    }
         
    for(Part part: request.getParts()){
        response.getWriter().println("=========================================================");
        response.getWriter().println("Name do campo file: "+part.getName() );
        response.getWriter().println("Tamanho: "+part.getSize()+" bytes" );
        response.getWriter().println("Content type: "+part.getContentType()  );
        response.getWriter().println( "Nome do arquivo: " + this.getFileName(part) );       
             
             
        for(String headerName : part.getHeaderNames()){
            response.getWriter().println("---------------------------------------------"  );
            response.getWriter().println("Header name: "+ headerName );
            response.getWriter().println( part.getHeader( headerName ) );
            response.getWriter().println("---------------------------------------------"  );
        }
 
         
        //grava o arquivo no disco
        File arquivo = new File( dir.getAbsolutePath() + "/" + getFileName(part) ); 
        part.write( arquivo.getAbsolutePath() );
        response.getWriter().println("=========================================================");
    }
             
}

Bom era isso, espero ter ajudado.