Servlet 3 Bestand Upload – @MultipartConfig, Deel

Vandaag zullen we kijken naar een Servlet 3-bestand uploadvoorbeeld met behulp van de annotatie @MultipartConfig en javax.servlet.http.Part. Enige tijd geleden schreef ik een artikel over Servlet-bestandsupload en ik gebruikte de Apache FileUpload API, maar hier zullen we de Servlet 3-bestandsuploadfunctie gebruiken.

Servlet 3-bestandsupload

Aangezien bestandsupload een veelvoorkomende taak is in webapplicaties, heeft Servlet-specificatie 3.0 aanvullende ondersteuning geboden voor het uploaden van bestanden naar de server en hoeven we niet afhankelijk te zijn van externe API’s hiervoor. In deze tutorial zullen we zien hoe we de Servlet 3.0 API kunnen gebruiken voor het uploaden van bestanden naar de server.

MultipartConfig

We moeten de Servlet voor het verwerken van bestandsuploads annoteren met de MultipartConfig-annotatie om multipart/form-data-verzoeken te verwerken die worden gebruikt voor het uploaden van bestanden naar de server. De MultipartConfig-annotatie heeft de volgende attributen:

  • fileSizeThreshold: We kunnen de drempelwaarde voor de bestandsgrootte opgeven waarbij het bestand naar de schijf wordt geschreven. De grootte wordt uitgedrukt in bytes, dus 1024*1024*10 is 10 MB.
  • locatie: Map waar bestanden standaard worden opgeslagen, de standaardwaarde is “”.
  • maxBestandsgrootte: Maximale grootte toegestaan voor het uploaden van een bestand, de waarde wordt opgegeven in bytes. De standaardwaarde is -1L, wat betekent onbeperkt.
  • maxAanvraaggrootte: Maximale grootte toegestaan voor een multipart/form-data aanvraag. Standaardwaarde is -1L, wat betekent onbeperkt.

Lees meer over annotaties op Java Annotations Tutorial.

Deelinterface

De interface vertegenwoordigt een onderdeel of formulieritem dat is ontvangen in een multipart/form-data POST-aanvraag. Enkele belangrijke methoden zijn getInputStream() en write(String fileName), die we kunnen gebruiken om bestanden te lezen en schrijven.

Wijzigingen in HttpServletRequest

Nieuwe methoden zijn toegevoegd aan HttpServletRequest om alle delen op te halen in een multipart/form-data-verzoek via de methode getParts(). We kunnen een specifiek deel ophalen met de methode getPart(String partName). Laten we een eenvoudig project bekijken waarin we bovenstaande API-methoden gebruiken om een bestand te uploaden met behulp van een servlet. Onze projectstructuur ziet eruit als de onderstaande afbeelding.

HTML-formulier

We hebben een eenvoudige html-pagina waar we het bestand kunnen selecteren om te uploaden en het verzoek naar de server kunnen verzenden om het te laten uploaden. 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>

Bestand Upload Servlet

Hier is onze implementatie van de Bestand Upload Servlet. 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 {
        // verkrijgt het absolute pad van de webtoepassing
        String applicationPath = request.getServletContext().getRealPath("");
        // construeert het pad van de map om het geüploade bestand op te slaan
        String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
         
        // maakt de opslagmap aan als deze niet bestaat
        File fileSaveDir = new File(uploadFilePath);
        if (!fileSaveDir.exists()) {
            fileSaveDir.mkdirs();
        }
        System.out.println("Upload File Directory="+fileSaveDir.getAbsolutePath());
        
        String fileName = null;
        // Haal alle delen op uit het verzoek en schrijf het naar het bestand op de server
        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 "";
    }
}

Let op het gebruik van de @MultipartConfig-annotatie om verschillende grootteparameters voor het uploaden van bestanden te specificeren. We moeten de request header “content-disposition” attribuut gebruiken om de bestandsnaam te krijgen die door de client is verzonden, we zullen het bestand met dezelfde naam opslaan. De maplocatie is relatief ten opzichte van de webtoepassing waar ik het bestand opsla, je kunt het configureren naar een andere locatie zoals in het Apache Commons FileUpload-voorbeeld.

Respons 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>

Implementatie Descriptor

Er staat niets nieuws in het web.xml-bestand voor het uploaden van servletbestanden, het wordt alleen gebruikt om de index.html als welkomstbestand in te stellen. 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>

Wanneer we nu de toepassing uitvoeren, krijgen we de volgende pagina’s als reactie. In de logs wordt de maplocatie getoond waar het bestand is opgeslagen en de informatie over de content-disposition-header.

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.

Download Servlet 3 Multipart File Upload Project
Download het Servlet 3 Multipart Bestand Upload Project.

Source:
https://www.digitalocean.com/community/tutorials/servlet-3-file-upload-multipartconfig-part