上一篇                     
               
			  Java如何实现文件上传下载?
- 后端开发
- 2025-06-11
- 4212
 在Java中实现文件上传通常使用Servlet的
 
 
Part接口或第三方库如Apache Commons FileUpload处理HTTP请求流;下载文件则通过设置响应头
 Content-Disposition并读取文件流写入响应输出流完成,核心步骤包括解析请求、读写文件流和异常处理。
在Web应用中,文件上传与下载是高频需求,本文详细讲解Java实现方案,涵盖核心API、安全实践及完整代码示例,帮助开发者构建健壮的文件传输功能。
环境准备
- 基础环境:JDK 8+、Servlet 3.0+(支持Part接口)、Tomcat 9+
- 可选库:Apache Commons FileUpload(传统表单上传) <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.5</version> </dependency> 
文件上传实现
方案1:Servlet API原生实现(推荐)
@WebServlet("/upload")
@MultipartConfig(maxFileSize = 1024 * 1024 * 10) // 限制10MB
public class FileUploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        try {
            Part filePart = request.getPart("file"); // "file"为表单字段名
            String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
            InputStream fileContent = filePart.getInputStream();
            // 存储到服务器(示例路径)
            Files.copy(fileContent, Paths.get("/uploads/" + fileName));
            response.getWriter().print("上传成功: " + fileName);
        } catch (Exception e) {
            response.sendError(500, "上传失败: " + e.getMessage());
        }
    }
} 
关键参数说明:
- @MultipartConfig:配置上传限制- maxFileSize:单文件最大字节数
- maxRequestSize:总请求最大字节数
- location:临时存储目录
 
方案2:Apache Commons FileUpload(兼容旧版)
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(10 * 1024 * 1024); // 10MB限制
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
    if (!item.isFormField()) { // 跳过普通表单字段
        String fileName = new File(item.getName()).getName();
        File storeFile = new File("/uploads/" + fileName);
        item.write(storeFile); // 保存文件
    }
} 
文件下载实现
@WebServlet("/download")
public class FileDownloadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        String fileName = request.getParameter("filename");
        Path filePath = Paths.get("/uploads/", fileName);
        try (InputStream in = Files.newInputStream(filePath);
             OutputStream out = response.getOutputStream()) {
            // 设置响应头
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename="" + fileName + """);
            // 流复制
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            response.sendError(404, "文件不存在");
        }
    }
} 
响应头解析:

- Content-Type: application/octet-stream:强制浏览器下载
- Content-Disposition: attachment:指定默认文件名
安全实践
-  文件类型校验 
 使用文件头(Magic Number)而非扩展名:byte[] header = Files.readAllBytes(filePath); if (!Arrays.equals(header, 0, 4, new byte[]{0x25, 0x50, 0x44, 0x46}, 0, 4)) { // PDF示例 throw new SecurityException("非规文件类型"); }
-  路径安全  - 使用Paths.get("/safe_dir/", fileName).normalize()防止路径遍历攻击
- 禁止用户自定义存储路径
 
- 使用
-  大小限制 - 服务端双重校验:前端表单限制 + 后端@MultipartConfig或setSizeMax()
 
- 服务端双重校验:前端表单限制 + 后端
-  重命名策略  String safeName = UUID.randomUUID() + "_" + fileName; // 避免文件名冲突 
前端表单示例
<!-- 上传表单 -->
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" accept=".pdf,.jpg,.png"> <!-- 前端过滤 -->
    <button type="submit">上传</button>
</form>
<!-- 下载链接 -->
<a href="/download?filename=report.pdf">下载报告</a> 
- 上传:优先使用Servlet 3.0+的Part接口,简洁高效
- 下载:重点控制响应头与流复制
- 安全:类型校验、路径规范、大小限制缺一不可
- 扩展建议: 
  - 大文件上传:分片传输(如Dropzone.js + 后台合并)
- 云存储:集成AWS S3或阿里云OSS SDK
 
引用说明:
- Servlet 3.0规范:Oracle官方文档
- Apache Commons FileUpload:Apache 2.0协议开源库
- 安全实践参考:OWASP文件上传防护指南
 
  
			