Hoje vamos examinar um exemplo de envio de arquivos Servlet 3 usando a anotação @MultipartConfig e javax.servlet.http.Part
. Algum tempo atrás, escrevi um artigo sobre Envio de Arquivos Servlet e usei a API Apache FileUpload, mas aqui usaremos o recurso de envio de arquivos do Servlet 3.
Envio de Arquivos Servlet 3
Como o envio de arquivos é uma tarefa comum em aplicações web, a especificação do Servlet 3.0 forneceu suporte adicional para enviar 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 de manipulação de envio de arquivos com a anotação MultipartConfig para lidar com solicitações multipart/form-data que são usadas para enviar arquivos para o servidor. A anotação MultipartConfig tem os seguintes atributos:
- fileSizeThreshold: Podemos especificar o limite de tamanho após o qual o arquivo será gravado no disco. O valor do tamanho está em bytes, então 1024*1024*10 equivale 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. O valor padrão é -1L, o que significa ilimitado.
- tamanhoMaximoRequisicao: Tamanho máximo permitido para a requisição multipart/form-data. O valor padrão é -1L, o que significa ilimitado.
Saiba mais sobre anotações em Tutorial de Anotações em Java.
Interface Parte
A interface Parte representa uma parte ou item de formulário recebido em uma solicitação POST multipart/form-data. Alguns métodos importantes são getInputStream()
e 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 por meio 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 API acima para enviar um arquivo usando um servlet. A estrutura do nosso projeto será semelhante à imagem abaixo.
Formulário HTML
Tempos uma página html simples onde podemos selecionar o arquivo para enviar e enviar uma 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 Arquivo
Aqui está a implementação do nosso Servlet de Upload de Arquivo. 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 ele 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 arquivo enviado. Precisamos usar o atributo do cabeçalho da solicitação “content-disposition” para obter o nome do arquivo enviado pelo cliente, e então 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 o envio de arquivos do servlet, ele é apenas usado para tornar o index.html o 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 de 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