How do I handle file uploads using Jakarta Servlet 6.0+?

In Jakarta Servlet 6.0+, file uploads can be handled efficiently using the native APIs provided by the servlet specifications. Here’s a step-by-step guide:

1. Enable Multipart Config for the Servlet

To handle file uploads, the servlet must be annotated with @MultipartConfig, which enables support for handling multipart/form-data requests. You can configure parameters such as maximum file size, total request size, and file location.

Example:

package org.kodejava.servlet;

import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;

import java.io.File;
import java.io.IOException;

@WebServlet("/upload")
@MultipartConfig(
        fileSizeThreshold = 1024 * 1024 * 2, // 2MB. Files above this size will be written to disk.
        maxFileSize = 1024 * 1024 * 10,      // 10MB. Maximum size for a single uploaded file.
        maxRequestSize = 1024 * 1024 * 50,   // 50MB. Maximum size of the entire request.
        location = "/tmp"                    // Temporary directory for uploaded files.
)
public class FileUploadServlet extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {

    // Ensure the request is indeed a multipart request
    if (!request.getContentType().startsWith("multipart/form-data")) {
      response.getWriter().println("Invalid request type");
      return;
    }

    // Retrieve the part associated with the upload form field
    Part filePart = request.getPart("file");  // "file" is the form field name
    if (filePart != null) {
      // Retrieve file information
      String fileName = extractFileName(filePart);
      long fileSize = filePart.getSize(); // Size of the file in bytes

      // Define file path for saving
      String uploadDir = getServletContext().getRealPath("") + File.separator + "uploads";
      File uploadDirFile = new File(uploadDir);
      if (!uploadDirFile.exists()) {
        uploadDirFile.mkdirs(); // Create directories if they don't exist
      }
      String filePath = uploadDir + File.separator + fileName;

      // Write the uploaded file to the target directory
      filePart.write(filePath);

      // Respond back to the client
      response.getWriter().println("File uploaded successfully to: " + filePath);
    } else {
      response.getWriter().println("File upload failed. Missing file part.");
    }
  }

  // Utility method to extract the file name from the HTTP header
  private String extractFileName(Part part) {
    String contentDisposition = part.getHeader("content-disposition");
    for (String content : contentDisposition.split(";")) {
      if (content.trim().startsWith("filename")) {
        return content.substring(content.indexOf("=") + 2, content.length() - 1); // Extract filename
      }
    }
    return "unknown";
  }
}

2. Create a Front-End Form

Ensure your front-end has a form with the enctype="multipart/form-data" attribute.

Example HTML Form:

<!DOCTYPE html>
<html>
<head>
    <title>File Upload</title>
</head>
<body>
    <h2>Upload a File</h2>
    <form method="post" action="/upload" enctype="multipart/form-data">
        <label for="file">Choose a file:</label>
        <input type="file" name="file" id="file" required>
        <br>
        <button type="submit">Upload</button>
    </form>
</body>
</html>

3. Explanation of Key Parts in the Code

  • @MultipartConfig Annotation:
    • fileSizeThreshold: Files larger than this threshold are written to disk instead of memory.
    • maxFileSize: The maximum size allowed for a single file.
    • maxRequestSize: The maximum size allowed for the entire request (including all parts).
    • location: Directory where files are stored temporarily. Files exceeding the threshold are saved here.
  • Part Object:
    • Represents a part in a multipart request. You can use it to get the file content, headers, and write it to a file.
  • extractFileName() Utility Function:
    • Extracts the file name from the content-disposition header of the Part.

4. File Storage Directory

Ensure the target directory exists (or is created) where the uploaded files will be stored. The example uses a directory inside your web application (uploads folder).
For production setups, consider storing files in external directories to avoid packaging issues.

5. Additional Considerations

  • Validation:
    • Validate the uploaded file (e.g., file type, size) for security reasons.
  • Error Handling:
    • Use appropriate exception handling for cases like large files (IllegalStateException) or I/O errors.
  • Security:
    • Always sanitize the file name and restrict file types to prevent malicious uploads.

6. Dependencies

If you’re using a Jakarta Servlet container (e.g., Apache Tomcat 10+), make sure the servlet API dependency exists in your pom.xml (or equivalent build file):

With this setup, your servlet will successfully handle file uploads in Jakarta Servlet 6.0+! Let me know if you have further questions or need additional details

Maven dependencies

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.1.0</version>
    <scope>provided</scope>
</dependency>

Maven Central

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.