JavaWeb 基于Servlet实现多文件上传(带大小限制+异常处理)实验总结
JavaWeb 基于Servlet实现多文件上传(带大小限制+异常处理)实验总结
一、实验概述
文件上传是 JavaWeb 开发中非常基础且高频的功能,常用于头像上传、资料提交、批量文件备份等场景。本次实验基于 Eclipse + Tomcat9 + Servlet + Apache Commons FileUpload 技术栈,实现双文件同时上传、自定义文件描述、单文件大小限制、总大小限制、异常捕获提示的完整多文件上传功能。
相比原生 Servlet 文件上传,使用 Commons-fileupload 工具类可以大幅简化解析表单、读取文件流、判断文件大小的逻辑,代码可读性更高、稳定性更强。
二、实验环境
-
开发工具:Eclipse IDE
-
服务器:Apache Tomcat 9
-
技术栈:JSP + Servlet + Commons-fileupload + Commons-io
-
项目类型:Dynamic Web Project
-
功能限制:单文件最大 50KB,总上传大小最大 10MB
三、实现原理
普通表单只能提交文本数据,而文件上传必须设置表单属性 enctype="multipart/form-data"。浏览器会将文件以二进制流的形式发送到服务器。
服务器端通过 Commons-fileupload 工具解析请求:
-
判断当前请求是否为文件上传请求;
-
创建文件上传工厂与解析器,设置单文件、总文件大小限制;
-
遍历解析表单字段,区分普通文本字段(文件描述)和文件字段;
-
读取文件名、文件大小、文件类型,自动创建服务器保存目录;
-
将文件写入服务器磁盘,并回显上传信息;
-
捕获文件超限、总大小超限等异常,给出前端提示。
四、项目结构
五、核心代码实现
1. 前端 JSP 上传页面(uploadHttpMulti.jsp)
提供两个文件描述输入框、两个文件选择框,支持重置与提交上传。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>多文件上传实验</title> </head> <body> <h3>多文件上传(单文件上限50KB)</h3> <form action="UploadHttpMultiServlet" method="post" enctype="multipart/form-data"> 文件1描述:<input type="text" name="fileDesc1"><br><br> 选择文件1:<input type="file" name="file1"><br><br> 文件2描述:<input type="text" name="fileDesc2"><br><br> 选择文件2:<input type="file" name="file2"><br><br> <input type="reset" value="重填"> <input type="submit" value="上传文件"> </form> </body> </html>
2. 后端 Servlet 核心代码(适配新版 fileupload2 无报错)
适配高版本 Tomcat + fileupload2,支持读取文件描述、文件信息回显、大小限制、异常捕获。
package com.servlet; import java.io.File; import java.io.IOException; import java.util.List; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.fileupload2.core.FileItem; import org.apache.commons.fileupload2.core.FileUploadBase; import org.apache.commons.fileupload2.core.DiskFileItemFactory; import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload; @WebServlet("/UploadHttpMultiServlet") public class UploadHttpMultiServlet extends HttpServlet { private static final long serialVersionUID = 1L; // 单文件最大50KB private static final long MAX_FILE_SIZE = 50 * 1024; // 单次请求总大小10MB private static final long MAX_REQUEST_SIZE = 10 * 1024 * 1024; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // 判断是否为文件上传请求 if (!JakartaServletFileUpload.isMultipartContent(request)) { response.getWriter().println("不是文件上传请求"); return; } DiskFileItemFactory factory = new DiskFileItemFactory(); JakartaServletFileUpload upload = new JakartaServletFileUpload(factory); upload.setFileSizeMax(MAX_FILE_SIZE); upload.setSizeMax(MAX_REQUEST_SIZE); try { List<FileItem> items = upload.parseRequest(request); response.getWriter().println("<h3>上传文件信息:</h3>"); String desc1 = ""; String desc2 = ""; int count = 1; for (FileItem item : items) { // 读取文本描述 if (item.isFormField()) { String fieldName = item.getFieldName(); String value = item.getString("UTF-8"); if ("fileDesc1".equals(fieldName)) { desc1 = value; } else if ("fileDesc2".equals(fieldName)) { desc2 = value; } continue; } // 处理文件 String fileName = item.getName(); if (fileName != null && fileName.contains("\\")) { fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); } String type = item.getContentType(); long size = item.getSize(); // 输出信息 response.getWriter().println("===== 第" + count + "个文件 ====<br/>"); response.getWriter().println("文件描述:" + (count == 1 ? desc1 : desc2) + "<br/>"); response.getWriter().println("文件名:" + fileName + "<br/>"); response.getWriter().println("文件类型:" + type + "<br/>"); response.getWriter().println("文件大小:" + size + " 字节<br/>"); // 保存文件 String realPath = getServletContext().getRealPath("/") + "uploadFiles"; File dir = new File(realPath); if (!dir.exists()) dir.mkdirs(); File saveFile = new File(dir, fileName); item.write(saveFile); response.getWriter().println("保存路径:" + saveFile.getAbsolutePath() + "<br/><hr/>"); count++; } } catch (Exception e) { // 精准捕获超限异常 if (e instanceof FileUploadBase.FileSizeLimitExceededException) { response.getWriter().println("<font color='red'>警告:单个文件超过50KB限制!</font>"); } else if (e instanceof FileUploadBase.SizeLimitExceededException) { response.getWriter().println("<font color='red'>警告:总上传大小超出限制!</font>"); } else { e.printStackTrace(); response.getWriter().println("上传失败:" + e.getMessage()); } } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } }
六、实验运行效果
1. 正常上传(小于50KB)
填写文件描述、选择两个小文件上传,页面成功回显:文件描述、文件名、文件类型、文件大小、服务器保存路径,项目自动生成 uploadFiles 文件夹保存文件。
2. 超限上传(大于50KB)
选择大文件时页面提示红色警告,拒绝上传,完美实现大小拦截功能。
3. 重填功能
点击重填按钮,所有输入框、文件选择框一键清空,表单重置正常。
七、实验踩坑总结(重点)
坑1:jar版本不匹配导致代码爆红
新版 fileupload2 包路径变更,旧代码org.apache.commons.fileupload 全部报错。解决方案:更换为org.apache.commons.fileupload2.core 新版导入路径,并使用JakartaServletFileUpload。
坑2:表单忘记添加 enctype 属性
没有 enctype="multipart/form-data" 无法传输二进制文件,导致上传空白、无响应。
坑3:能运行但页面空白、无报错
原因:Tomcat 未正确部署项目、缓存未刷新、端口占用。解决:重启 Tomcat、重新 Run on Server、使用 Tomcat 原生部署路径。
坑4:中文乱码
必须在 Servlet 首行设置request.setCharacterEncoding("UTF-8"),同时项目编码统一为 UTF-8。
八、实验总结
本次实验成功基于 Servlet + Commons-fileupload 实现了双文件批量上传、自定义描述、大小限制、异常提示、自动存储完整功能。理解了文件上传的核心原理:表单二进制编码、文件流解析、服务器磁盘写入、异常拦截机制。
同时解决了新版 jar 包适配、编码乱码、部署失败、页面无响应等常见问题,为后续学习头像上传、批量资源上传、文件管理系统打下扎实基础。
更多推荐



所有评论(0)