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

Java中实现文件上传通常使用Servlet的Part接口或第三方库如Apache Commons FileUpload处理HTTP请求流;下载文件则通过设置响应头Content-Disposition并读取文件流写入响应输出流完成,核心步骤包括解析请求、读写文件流和异常处理。

在Web应用中,文件上传与下载是高频需求,本文详细讲解Java实现方案,涵盖核心API、安全实践及完整代码示例,帮助开发者构建健壮的文件传输功能。

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


环境准备

  • 基础环境: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:指定默认文件名

安全实践

  1. 文件类型校验
    使用文件头(Magic Number)而非扩展名:

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

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

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

    • 服务端双重校验:前端表单限制 + 后端@MultipartConfigsetSizeMax()
  4. 重命名策略

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

    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文件上传防护指南

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/18836.html

(0)
酷盾叔的头像酷盾叔
上一篇 2025年6月11日 00:47
下一篇 2025年6月11日 00:56

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN