【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 接口是简单有效的选择。

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

相关推荐
坐吃山猪35 分钟前
SpringBoot01-配置文件
java·开发语言
我叫汪枫1 小时前
《Java餐厅的待客之道:BIO, NIO, AIO三种服务模式的进化》
java·开发语言·nio
yaoxtao1 小时前
java.nio.file.InvalidPathException异常
java·linux·ubuntu
Swift社区2 小时前
从 JDK 1.8 切换到 JDK 21 时遇到 NoProviderFoundException 该如何解决?
java·开发语言
DKPT3 小时前
JVM中如何调优新生代和老生代?
java·jvm·笔记·学习·spring
phltxy3 小时前
JVM——Java虚拟机学习
java·jvm·学习
seabirdssss5 小时前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续5 小时前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben0445 小时前
ReAct模式解读
java·ai