Hoy echaremos un vistazo al Ejemplo de Carga de Archivos Servlet 3 utilizando la anotación @MultipartConfig y javax.servlet.http.Part
. Hace algún tiempo escribí un artículo sobre Carga de Archivos Servlet y utilicé la API Apache FileUpload, pero aquí utilizaremos la función de Carga de Archivos Servlet 3.
Carga de Archivos Servlet 3
Dado que la carga de archivos es una tarea común en las aplicaciones web, las especificaciones del Servlet 3.0 proporcionaron soporte adicional para cargar archivos en el servidor y no tenemos que depender de ninguna API de terceros para esto. En este tutorial veremos cómo podemos usar la API Servlet 3.0 para cargar archivos en el servidor.
MultipartConfig
Necesitamos anotar el servlet controlador de carga de archivos con la anotación MultipartConfig para manejar las solicitudes multipart/form-data que se utilizan para cargar archivos en el servidor. La anotación MultipartConfig tiene los siguientes atributos:
- fileSizeThreshold: Podemos especificar el umbral de tamaño después del cual el archivo se escribirá en el disco. El valor del tamaño está en bytes, por lo que 1024*1024*10 son 10 MB.
- ubicación: Directorio donde se almacenarán los archivos de forma predeterminada, su valor predeterminado es “”.
- tamañoMaximoArchivo: Tamaño máximo permitido para cargar un archivo, su valor se proporciona en bytes. Su valor predeterminado es -1L, lo que significa ilimitado.
- tamañoMaximoSolicitud: Tamaño máximo permitido para la solicitud multipart/form-data. El valor predeterminado es -1L, lo que significa ilimitado.
Lea más sobre las anotaciones en Tutorial de Anotaciones en Java.
Interfaz Parte
La interfaz Parte representa una parte o elemento de formulario que se recibió en una solicitud POST multipart/form-data. Algunos métodos importantes son getInputStream()
, write(String fileName)
que podemos usar para leer y escribir archivos.
Cambios en HttpServletRequest
Se agregaron nuevos métodos en HttpServletRequest
para obtener todas las partes en una solicitud multipart/form-data a través del método getParts()
. Podemos obtener una parte específica usando el método getPart(String partName)
. Veamos un proyecto simple donde usaremos los métodos de API anteriores para cargar un archivo usando un servlet. La estructura de nuestro proyecto se verá como la imagen a continuación.
Formulario HTML
Tenemos una página HTML simple donde podemos seleccionar el archivo para cargar y enviar la solicitud al servidor para que lo cargue. 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>
Servlet de Carga de Archivos
Aquí está nuestra implementación del Servlet de Carga de Archivos. 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 {
// obtiene la ruta absoluta de la aplicación web
String applicationPath = request.getServletContext().getRealPath("");
// construye la ruta del directorio para guardar el archivo cargado
String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
// crea el directorio de guardado si no existe
File fileSaveDir = new File(uploadFilePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdirs();
}
System.out.println("Upload File Directory="+fileSaveDir.getAbsolutePath());
String fileName = null;
// Obtén todas las partes de la solicitud y escríbelas en el archivo en el 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 "";
}
}
Observa el uso de la anotación @MultipartConfig para especificar diferentes parámetros de tamaño para la carga de archivos. Necesitamos utilizar el atributo “content-disposition” del encabezado de la solicitud para obtener el nombre del archivo enviado por el cliente, guardaremos el archivo con el mismo nombre. La ubicación del directorio es relativa a la aplicación web donde estoy guardando el archivo, puedes configurarlo en otra ubicación, como en el ejemplo de Apache Commons FileUpload.
Respuesta 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>
Descriptor de Despliegue
No hay nada nuevo en el archivo web.xml para la carga de archivos del servlet, solo se utiliza para hacer que el index.html sea el archivo de bienvenida. 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>
Ahora, cuando ejecutamos la aplicación, obtenemos las siguientes páginas como respuesta.
Los registros mostrarán la ubicación del directorio donde se guarda el archivo y la información del encabezado 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.
Descargar Proyecto de Subida de Archivos Multiparte Servlet 3
Source:
https://www.digitalocean.com/community/tutorials/servlet-3-file-upload-multipartconfig-part