【Spring MVC】小文件上传的多种方法

文章目录

  • 方法参数
  • 单文件上传
    • [1. MultipartFile 的 transferTo(File dest)](#1. MultipartFile 的 transferTo(File dest))
    • [2. MultipartFile 的 transferTo(Path dest)](#2. MultipartFile 的 transferTo(Path dest))
    • [3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption... options)](#3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption... options))
    • [4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption... options)](#4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption... options))
    • [5. HttpServletRequest 的 getPart(String var1)](#5. HttpServletRequest 的 getPart(String var1))
  • 多文件上传(兼容单文件)
    • [1. MultipartFile[ ] + 前四种上传方法](#1. MultipartFile[ ] + 前四种上传方法)
    • [2. List<MultipartFile> + 前四种上传方法](#2. List<MultipartFile> + 前四种上传方法)
    • [3. MultipartHttpServletRequest + 前四种上传方法](#3. MultipartHttpServletRequest + 前四种上传方法)
    • [4. HttpServletRequest 的 getParts()](#4. HttpServletRequest 的 getParts())
  • 补充
  • 总结

Win、JDK 17、 Spring Boot 3.1.2

方法参数

  1. Spring 的 MultipartFile(最常用)
  2. Spring 的 MultipartHttpServletRequest
  3. Servlet 的 HttpServletRequest(原生)

单文件上传

1. MultipartFile 的 transferTo(File dest)

java 复制代码
@PostMapping("/upload-1")
public String upload1(@RequestPart("file") MultipartFile mf) throws IOException {
    String filename = mf.getOriginalFilename();
    mf.transferTo(new File("d:/", filename));

    return "upload success";
}

2. MultipartFile 的 transferTo(Path dest)

java 复制代码
@PostMapping("/upload-2")
public String upload2(@RequestParam("file") MultipartFile mf) throws IOException {
    String filename = mf.getOriginalFilename();
    Path path = Paths.get("upload", filename);
    mf.transferTo(path);

    return "upload success";
}

3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption... options)

java 复制代码
@PostMapping("/upload-3")
public String upload3(@RequestParam("file") MultipartFile mf) throws IOException {
    String filename = mf.getOriginalFilename();
    Path path = Paths.get("upload", filename);
    Files.write(path, mf.getBytes());

    return "upload success";
}

4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption... options)

java 复制代码
@PostMapping("/upload-4")
public String upload4(@RequestParam("file") MultipartFile mf) throws IOException {
    String filename = mf.getOriginalFilename();
    Path path = Paths.get("upload", filename);
    // 若文件已存在,则会抛出 FileAlreadyExistsException
    Files.copy(mf.getInputStream(), path);

    return "upload success";
}

5. HttpServletRequest 的 getPart(String var1)

java 复制代码
public String upload8(HttpServletRequest req) throws ServletException, IOException {
    // 获取上传的文件流,单文件
    Part filePart = req.getPart("file");
    String filename = filePart.getSubmittedFileName();

    // 构建目标文件对象
    Path path = Paths.get("upload", filename);
    byte[] bytes = filePart.getInputStream().readAllBytes();
    InputStream in = filePart.getInputStream();

    // Files.write(path, bytes);
    // Files.copy(in,path);

    return "upload success";
}

多文件上传(兼容单文件)

1. MultipartFile[ ] + 前四种上传方法

java 复制代码
@PostMapping("/upload-5")
public String upload5(@RequestParam("files") MultipartFile[] files) {
    for (MultipartFile mf : files) {
        // 同理又有四种
        // mf.transferTo(File dest)
        // mf.transferTo(Path dest)
        // Files.write(Path path, byte[] bytes, OpenOption... options)
        // Files.copy(mf.getInputStream(), path);
    }

    return "upload success";
}

2. List<MultipartFile> + 前四种上传方法

java 复制代码
@PostMapping("/upload-6")
public String upload6(@RequestParam("files") List<MultipartFile> files) {
    for (MultipartFile mf : files) {
        // 同理又有四种
        // mf.transferTo(File dest)
        // mf.transferTo(Path dest)
        // Files.write(Path path, byte[] bytes, OpenOption... options)
        // Files.copy(mf.getInputStream(), path);
    }

    return "upload success";
}

3. MultipartHttpServletRequest + 前四种上传方法

java 复制代码
@PostMapping("/upload-7")
public String upload7(MultipartHttpServletRequest req) {
    req.getFileNames().forEachRemaining(name -> {
        for (MultipartFile mf : req.getFiles(name)) {
            // 同理又有四种
            // mf.transferTo(File dest)
            // mf.transferTo(Path dest)
            // Files.write(Path path, byte[] bytes, OpenOption... options)
            // Files.copy(mf.getInputStream(), path);
        }
    });

    return "upload success";
}

4. HttpServletRequest 的 getParts()

java 复制代码
@PostMapping("/upload-9")
public String upload9(HttpServletRequest req) throws ServletException, IOException {
    Collection<Part> parts = req.getParts();
    
    for (Part part : parts) {
        String filename = part.getSubmittedFileName();

        Path path = Paths.get("upload", filename);
        byte[] bytes = part.getInputStream().readAllBytes();
        InputStream in = part.getInputStream();

        // Files.write(path, bytes);
        // Files.copy(in,path);
    }

    return "upload success";
}

补充

以上方法仅为示例代码,注意 NPE

以上方法仅适用于小文件上传,不适合上百 MB 的大文件上传

Files.copy() 无法覆盖文件,会抛异常

@RequestPart 可替代 @RequestParam

@RequestParam@RequestPart 都是Spring框架中用于处理HTTP请求参数的注解,但它们在处理文件上传时有一些区别。

  1. @RequestParam:

    • 用于处理普通的表单字段和查询参数,适用于处理常规的请求参数。
    • 在处理文件上传时,可以用于接收文件的元数据(如文件名、大小等),但无法直接获取文件的内容。
    • 对于文件上传,@RequestParam 需要配合 MultipartFile 类型参数来获取文件的内容。

    示例:

    java 复制代码
    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {
        // 处理文件上传逻辑
        // ...
    }
  2. @RequestPart:

    • 用于处理文件上传请求,特别适用于处理发送 multipart/form-data 类型的请求。
    • 允许直接获取文件的内容,不需要再额外使用 MultipartFile 类型参数来获取文件内容。
    • 可以用于接收文件的元数据(如文件名、大小等),也可以直接获取文件的字节流。

    示例:

    java 复制代码
    @PostMapping("/upload")
    public String handleFileUpload(@RequestPart("file") byte[] fileBytes,
                                   @RequestPart("file") InputStream fileInputStream,
                                   @RequestPart("file") Part filePart) {
        // 处理文件上传逻辑
        // ...
    }

综上所述,@RequestParam 用于处理常规的请求参数和文件元数据,需要额外使用 MultipartFile 类型参数来获取文件内容。而 @RequestPart 则更适用于处理文件上传请求,允许直接获取文件的内容,并且可以用于接收文件元数据。

在实际使用中,你可以根据请求的具体内容和需求来选择合适的注解,以及结合相应的处理方式。如果仅处理文件上传,使用 @RequestPart 更为直接方便;如果需要处理普通请求参数和文件上传一起,可以使用 @RequestParam 来处理。

总结

Spring MVC 提供了多种方法来处理文件上传,开发者可以根据项目需求和性能考虑选择适合的方法。对于小文件上传,使用 MultipartFile 接口是简单有效的选择。

无论选择哪种方法,都应该注意文件上传过程中的安全性和性能,避免潜在的漏洞和性能问题。合理设置文件大小限制,处理异常情况,以及对文件上传进行必要的验证和授权,都是保障文件上传功能正常运作的重要因素。

相关推荐
Seven971 分钟前
BIO详解:解锁阻塞IO的使用方式
java
oak隔壁找我10 小时前
JVM常用调优参数
java·后端
蝎子莱莱爱打怪14 小时前
OpenClaw 从零配置指南:接入飞书 + 常用命令 + 原理图解
java·后端·ai编程
狼爷16 小时前
Go 没有 override?别硬套继承!用接口+嵌入,写更清爽的“覆盖”逻辑
java·go
小兔崽子去哪了18 小时前
Java 自动化部署
java·后端
ma_king18 小时前
入门 java 和 数据库
java·数据库·后端
后端AI实验室18 小时前
我用Cursor开发了3个月,整理出这套提效4倍的工作流
java·ai
码路飞1 天前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
SimonKing1 天前
OpenCode AI编程助手如何添加Skills,优化项目!
java·后端·程序员
Seven971 天前
剑指offer-80、⼆叉树中和为某⼀值的路径(二)
java