导读:本期聚焦于小伙伴创作的《Apache Commons FileUpload如何手动解析multipart请求流》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Apache Commons FileUpload如何手动解析multipart请求流》有用,将其分享出去将是对创作者最好的鼓励。

Apache Commons FileUpload是Apache基金会提供的用于处理HTTP multipart请求的开源组件,能够解析包含文件和普通表单字段的混合请求流,在Java Web开发中广泛用于实现文件上传功能。手动使用该组件解析请求流,可以跳过框架的默认封装,更灵活地控制上传过程,满足特殊的业务需求。

Apache Commons FileUpload如何手动解析multipart请求流

环境准备

首先需要在项目中引入Apache Commons FileUpload及其依赖的Apache Commons IO组件,如果使用Maven管理项目,可以在pom.xml中添加以下依赖:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.5</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.15.1</version>
</dependency>

核心解析步骤

1. 判断请求是否为multipart类型

在解析之前,需要先判断当前HTTP请求是否为multipart格式,避免对非上传请求执行无效解析。可以通过ServletFileUploadisMultipartContent方法完成判断:

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.http.HttpServletRequest;

public boolean checkMultipartRequest(HttpServletRequest request) {
    // 判断请求是否为multipart类型
    return ServletFileUpload.isMultipartContent(request);
}

2. 创建文件上传处理器并设置限制

创建ServletFileUpload实例后,可以设置上传文件的大小限制、请求总大小限制等参数,避免恶意上传大文件占用服务器资源:

import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.File;

public ServletFileUpload initFileUpload() {
    // 创建磁盘文件项工厂,设置临时文件存储目录和大小阈值
    DiskFileItemFactory factory = new DiskFileItemFactory();
    // 设置内存中存储的最大字节数,超过则生成临时文件
    factory.setSizeThreshold(1024 * 1024);
    // 设置临时文件存储目录,这里使用系统临时目录
    factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
    
    // 创建文件上传处理器
    ServletFileUpload upload = new ServletFileUpload(factory);
    // 设置单个文件最大大小为10MB
    upload.setFileSizeMax(10 * 1024 * 1024);
    // 设置整个请求的最大大小为50MB
    upload.setSizeMax(50 * 1024 * 1024);
    // 设置请求头的字符编码,解决普通字段中文乱码问题
    upload.setHeaderEncoding("UTF-8");
    
    return upload;
}

3. 解析请求流获取文件项

调用ServletFileUploadparseRequest方法,即可解析请求流,得到所有表单项的集合,每个表单项对应一个FileItem实例:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

public List<FileItem> parseRequestItems(HttpServletRequest request) throws FileUploadException {
    ServletFileUpload upload = initFileUpload();
    // 解析请求,获取所有表单项
    return upload.parseRequest(request);
}

4. 区分处理普通字段和文件字段

遍历解析得到的FileItem集合,通过isFormField方法判断当前项是普通表单字段还是文件字段,分别进行处理:

import org.apache.commons.fileupload.FileItem;
import java.io.File;
import java.io.InputStream;
import java.util.List;

public void processFileItems(List<FileItem> items) throws Exception {
    for (FileItem item : items) {
        if (item.isFormField()) {
            // 处理普通表单字段
            String fieldName = item.getFieldName();
            // 获取字段值,使用UTF-8编码避免乱码
            String fieldValue = item.getString("UTF-8");
            System.out.println("普通字段名:" + fieldName + ",值:" + fieldValue);
        } else {
            // 处理文件字段
            String fileName = item.getName();
            // 获取输入流读取文件内容
            InputStream fileStream = item.getInputStream();
            // 可以将文件保存到指定路径,这里示例保存到当前项目的upload目录下
            String savePath = "upload/" + fileName;
            File saveFile = new File(savePath);
            // 确保父目录存在
            if (!saveFile.getParentFile().exists()) {
                saveFile.getParentFile().mkdirs();
            }
            item.write(saveFile);
            System.out.println("文件保存成功,路径:" + savePath);
            // 处理完成后清理临时文件
            item.delete();
        }
    }
}

完整示例整合

以下是一个在Servlet中手动解析multipart请求流的完整示例,将上述步骤整合到一起:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class FileUploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        // 判断是否为multipart请求
        if (!ServletFileUpload.isMultipartContent(request)) {
            response.getWriter().write("当前请求不是multipart类型");
            return;
        }
        try {
            // 初始化上传处理器
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(1024 * 1024);
            factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
            
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setFileSizeMax(10 * 1024 * 1024);
            upload.setSizeMax(50 * 1024 * 1024);
            upload.setHeaderEncoding("UTF-8");
            
            // 解析请求获取表单项
            List<FileItem> items = upload.parseRequest(request);
            // 处理表单项
            for (FileItem item : items) {
                if (item.isFormField()) {
                    String fieldName = item.getFieldName();
                    String fieldValue = item.getString("UTF-8");
                    System.out.println("普通字段:" + fieldName + " = " + fieldValue);
                } else {
                    String fileName = item.getName();
                    if (fileName == null || fileName.trim().isEmpty()) {
                        continue;
                    }
                    // 简化文件名,去掉路径部分
                    fileName = new File(fileName).getName();
                    String savePath = this.getServletContext().getRealPath("/upload") + File.separator + fileName;
                    File saveFile = new File(savePath);
                    if (!saveFile.getParentFile().exists()) {
                        saveFile.getParentFile().mkdirs();
                    }
                    item.write(saveFile);
                    item.delete();
                    response.getWriter().write("文件上传成功,文件名:" + fileName);
                }
            }
        } catch (FileUploadException e) {
            response.getWriter().write("文件上传失败:" + e.getMessage());
        } catch (Exception e) {
            response.getWriter().write("处理请求失败:" + e.getMessage());
        }
    }
}

注意事项

  • 解析请求流时,parseRequest方法会消耗请求的输入流,因此同一个请求不能重复调用该方法,否则会解析失败。
  • 处理文件字段时,getName方法返回的完整路径在某些浏览器中会包含客户端本地路径,需要手动截取文件名部分再保存。
  • 临时文件在使用完成后要及时调用delete方法清理,避免占用服务器磁盘空间。
  • 如果项目中同时使用了Spring MVC等框架,需要确保框架没有提前解析multipart请求,否则手动解析会获取不到表单项。

Apache_Commons_FileUploadmultipart请求请求流解析文件上传Servlet修改时间:2026-06-12 07:48:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。