Servlet File Upload
@MultipartConfig and Part Interface
Servlet 3.0 introduced built-in multipart/form-data support via the @MultipartConfig annotation and the Part interface. No third-party library is needed.
- @MultipartConfig — Annotates the servlet to handle multipart requests. Configures file size limits and temp storage.
- request.getPart(name) — Returns a single
Partfor the given field name. - request.getParts() — Returns all parts (for multiple file uploads).
- Part.write(path) — Saves the uploaded file to disk.
package com.example;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.*;
import java.nio.file.*;
@WebServlet("/upload")
@MultipartConfig(
fileSizeThreshold = 1024 * 1024, // 1 MB — write to disk if larger
maxFileSize = 1024 * 1024 * 10, // 10 MB max per file
maxRequestSize = 1024 * 1024 * 50 // 50 MB max total request
)
public class FileUploadServlet extends HttpServlet {
// Directory to save uploaded files (outside webroot for security)
private static final String UPLOAD_DIR = "/var/uploads/";
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/views/upload.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get the uploaded file part
Part filePart = request.getPart("file");
// Get the original filename submitted by the browser
String fileName = getFileName(filePart);
if (fileName == null || fileName.isEmpty()) {
request.setAttribute("error", "No file selected.");
request.getRequestDispatcher("/WEB-INF/views/upload.jsp").forward(request, response);
return;
}
// Validate file type (only images allowed)
String contentType = filePart.getContentType();
if (!contentType.startsWith("image/")) {
request.setAttribute("error", "Only image files are allowed.");
request.getRequestDispatcher("/WEB-INF/views/upload.jsp").forward(request, response);
return;
}
// Save the file to the upload directory
Path uploadPath = Paths.get(UPLOAD_DIR);
if (!Files.exists(uploadPath)) Files.createDirectories(uploadPath);
filePart.write(UPLOAD_DIR + fileName);
request.setAttribute("message", "File '" + fileName + "' uploaded successfully.");
request.getRequestDispatcher("/WEB-INF/views/upload.jsp").forward(request, response);
}
// Extract filename from Content-Disposition header
private String getFileName(Part part) {
String contentDisposition = part.getHeader("content-disposition");
for (String token : contentDisposition.split(";")) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf('=') + 1).trim()
.replace("\"", "");
}
}
return null;
}
}
<%-- WEB-INF/views/upload.jsp --%>
<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head><title>File Upload</title></head>
<body>
<h2>Upload File</h2>
<c:if test="${not empty message}">
<p style="color:green;">${message}</p>
</c:if>
<c:if test="${not empty error}">
<p style="color:red;">${error}</p>
</c:if>
<!-- enctype="multipart/form-data" is REQUIRED for file uploads -->
<form action="${pageContext.request.contextPath}/upload"
method="post" enctype="multipart/form-data">
<label>Select file: <input type="file" name="file" accept="image/*" /></label>
<br/><br/>
<button type="submit">Upload</button>
</form>
</body>
</html>
Multiple File Upload
@WebServlet("/multi-upload")
@MultipartConfig(maxFileSize = 1024 * 1024 * 5) // 5 MB per file
public class MultiUploadServlet extends HttpServlet {
private static final String UPLOAD_DIR = "/var/uploads/";
private static final Set<String> ALLOWED_TYPES = Set.of(
"image/jpeg", "image/png", "image/gif", "application/pdf");
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<String> uploaded = new ArrayList<>();
List<String> errors = new ArrayList<>();
// Iterate over all parts in the multipart request
for (Part part : request.getParts()) {
// Skip non-file fields (text inputs, etc.)
if (part.getContentType() == null) continue;
String fileName = getFileName(part);
if (fileName == null || fileName.isEmpty()) continue;
// Validate MIME type
if (!ALLOWED_TYPES.contains(part.getContentType())) {
errors.add(fileName + ": unsupported file type.");
continue;
}
// Validate file size (redundant with @MultipartConfig but explicit)
if (part.getSize() > 5 * 1024 * 1024) {
errors.add(fileName + ": exceeds 5 MB limit.");
continue;
}
// Save file
part.write(UPLOAD_DIR + fileName);
uploaded.add(fileName);
}
request.setAttribute("uploaded", uploaded);
request.setAttribute("errors", errors);
request.getRequestDispatcher("/WEB-INF/views/upload-result.jsp")
.forward(request, response);
}
private String getFileName(Part part) {
String cd = part.getHeader("content-disposition");
if (cd == null) return null;
for (String token : cd.split(";")) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf('=') + 1).trim().replace("\"", "");
}
}
return null;
}
}
@MultipartConfig Attributes
| Attribute | Default | Description |
|---|---|---|
location | "" | Temp directory for parts during processing |
maxFileSize | -1 (unlimited) | Max size in bytes for a single uploaded file |
maxRequestSize | -1 (unlimited) | Max size in bytes for the entire multipart request |
fileSizeThreshold | 0 | File size above which the part is written to disk (vs memory) |
<%-- multi-upload.jsp --%>
<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<head><title>Multiple File Upload</title></head>
<body>
<h2>Upload Multiple Files</h2>
<form action="${pageContext.request.contextPath}/multi-upload"
method="post" enctype="multipart/form-data">
<!-- multiple attribute allows selecting multiple files -->
<label>Select files:
<input type="file" name="files" multiple
accept=".jpg,.jpeg,.png,.gif,.pdf" />
</label>
<br/><br/>
<button type="submit">Upload All</button>
</form>
</body>
</html>
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.