Hoje vamos analisar um exemplo de upload de arquivo Servlet 3 usando a anotação @MultipartConfig e javax.servlet.http.Part
. Algum tempo atrás, escrevi um artigo sobre Upload de Arquivo Servlet e usei a API Apache FileUpload, mas aqui vamos utilizar a funcionalidade de upload de arquivo do Servlet 3.
Upload de Arquivo Servlet 3
Dado que o upload de arquivos é uma tarefa comum em aplicações web, a especificação Servlet 3.0 forneceu suporte adicional para o envio de arquivos para o servidor, e não precisamos depender de APIs de terceiros para isso. Neste tutorial, veremos como podemos usar a API Servlet 3.0 para enviar arquivos para o servidor.
MultipartConfig
É necessário anotar o servlet manipulador de upload de arquivo com a anotação MultipartConfig para lidar com solicitações multipart/form-data, que são usadas para fazer upload de arquivos para o servidor. A anotação MultipartConfig possui os seguintes atributos:
- fileSizeThreshold: Podemos especificar o limiar de tamanho após o qual o arquivo será gravado no disco. O valor do tamanho está em bytes, então 1024*1024*10 é equivalente a 10 MB.
- localização: Diretório onde os arquivos serão armazenados por padrão, o valor padrão é “”.
- tamanhoMaximoArquivo: Tamanho máximo permitido para o upload de um arquivo, o valor é fornecido em bytes. Seu valor padrão é -1L, o que significa ilimitado.
- tamanhoMaximoRequisicao: Tamanho máximo permitido para uma requisição multipart/form-data. O valor padrão é -1L, o que significa ilimitado.
Leia mais sobre anotações em Tutorial de Anotações em Java.
Interface Part
A interface Part representa uma parte ou item de formulário recebido em uma solicitação POST multipart/form-data. Alguns métodos importantes são getInputStream()
, write(String fileName)
que podemos usar para ler e escrever arquivos.
Alterações no HttpServletRequest
Novos métodos foram adicionados em HttpServletRequest
para obter todas as partes em uma solicitação multipart/form-data através do método getParts()
. Podemos obter uma parte específica usando o método getPart(String partName)
. Vamos ver um projeto simples onde usaremos os métodos acima da API para fazer upload de um arquivo usando um servlet. A estrutura do nosso projeto será semelhante à imagem abaixo.
Formulário HTML
Temos uma página HTML simples onde podemos selecionar o arquivo para fazer upload e enviar a solicitação ao servidor para que ele seja carregado. index.html
<html>
<head></head>
<body>
<form action="FileUploadServlet" method="post" enctype="multipart/form-data">
Select File to Upload:<input type="file" name="fileName">
<br>
<input type="submit" value="Upload">
</form>
</body>
</html>
Serviço de Upload de Arquivos
Aqui está a implementação do nosso Servlet de Upload de Arquivos. FileUploadServlet.java
package com.journaldev.servlet;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/FileUploadServlet")
@MultipartConfig(fileSizeThreshold=1024*1024*10, // 10 MB
maxFileSize=1024*1024*50, // 50 MB
maxRequestSize=1024*1024*100) // 100 MB
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 205242440643911308L;
/**
* Directory where uploaded files will be saved, its relative to
* the web application directory.
*/
private static final String UPLOAD_DIR = "uploads";
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// obtém o caminho absoluto da aplicação web
String applicationPath = request.getServletContext().getRealPath("");
// constrói o caminho do diretório para salvar o arquivo carregado
String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
// cria o diretório de salvamento se não existir
File fileSaveDir = new File(uploadFilePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdirs();
}
System.out.println("Upload File Directory="+fileSaveDir.getAbsolutePath());
String fileName = null;
// Obtém todas as partes da solicitação e escreve no arquivo no servidor
for (Part part : request.getParts()) {
fileName = getFileName(part);
part.write(uploadFilePath + File.separator + fileName);
}
request.setAttribute("message", fileName + " File uploaded successfully!");
getServletContext().getRequestDispatcher("/response.jsp").forward(
request, response);
}
/**
* Utility method to get file name from HTTP header content-disposition
*/
private String getFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
System.out.println("content-disposition header= "+contentDisp);
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf("=") + 2, token.length()-1);
}
}
return "";
}
}
Observe o uso da anotação @MultipartConfig para especificar diferentes parâmetros de tamanho para o upload do arquivo. Precisamos usar o atributo “content-disposition” do cabeçalho da solicitação para obter o nome do arquivo enviado pelo cliente, salvaremos o arquivo com o mesmo nome. A localização do diretório é relativa à aplicação web onde estou salvando o arquivo, você pode configurá-lo para algum outro local como no exemplo do Apache Commons FileUpload.
Resposta JSP
A simple JSP page that will be sent as response to client once the file is uploaded successfully to server. response.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Upload File Response</title>
</head>
<body>
<%-- Using JSP EL to get message attribute value from request scope --%>
<h2>${requestScope.message}</h2>
</body>
</html>
Descritor de Implantação
Não há nada de novo no arquivo web.xml para upload de arquivo servlet, ele é apenas usado para tornar o index.html como arquivo de boas-vindas. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ServletFileUploadExample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Agora, quando executamos a aplicação, obtemos as seguintes páginas como resposta.
Os logs mostrarão a localização do diretório onde o arquivo é salvo e as informações do cabeçalho “content-disposition”.
Upload File Directory=/Users/pankaj/Documents/workspace/j2ee/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ServletFileUploadExample/uploads
content-disposition header= form-data; name="fileName"; filename="IMG_2046.jpg"
I am running Tomcat through Eclipse, that’s why file location is like this. If you run tomcat through command line and deploy application by exporting as WAR file into webapps directory, you will get different structure but a clear one.
Source:
https://www.digitalocean.com/community/tutorials/servlet-3-file-upload-multipartconfig-part