当前位置:首页 > 后端开发 > 正文

Java如何实现文件上传下载?

在 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()); } } }

关键参数说明

Java如何实现文件上传下载? 第1张

  • @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:指定默认文件名


安全实践

  1. 文件类型校验

    使用文件头(Magic Number)而非扩展名:

    Java如何实现文件上传下载? 第2张

    byte[] header = Files.readAllBytes(filePath); if (!Arrays.equals(header, 0, 4, new byte[]{0x25, 0x50, 0x44, 0x46}, 0, 4)) { // PDF示例 throw new SecurityException("非法文件类型"); }

  2. 路径安全

    Java如何实现文件上传下载? 第3张

    • 使用Paths.get("/safe_dir/", fileName).normalize()防止路径遍历攻破
    • 禁止用户自定义存储路径
  3. 大小限制

    • 服务端双重校验:前端表单限制 + 后端@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文件上传防护指南

0