原文: https://howtodoinjava.com/spring-restful/multipart-multiple-uploads-example/

了解如何使用 Spring REST API 接受上传多个多部分二进制文件(例如 jpeg 图像),这些文件接受MultipartFile请求的数组。

1. Maven 依赖

除了 spring webmvc 之外,我们还将在类路径中需要commons-fileuploadcommons-io

pom.xml

  1. dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-webmvc</artifactId>
  4. <version>5.1.6.RELEASE</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>commons-fileupload</groupId>
  8. <artifactId>commons-fileupload</artifactId>
  9. <version>1.4</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>commons-io</groupId>
  13. <artifactId>commons-io</artifactId>
  14. <version>2.6</version>
  15. </dependency>

2. 配置CommonsMultipartResolver

它是commons-fileupload的基于 Servlet 的MultipartResolver实现。 它提供maxUploadSizemaxInMemorySizedefaultEncoding设置作为 bean 属性。

此类的目的是将临时文件保存到 Servlet 容器的临时目录中。

rest-servlet.xml

  1. <beans>
  2. ...
  3. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  4. <property name="maxUploadSize" value="1000000"/>
  5. </bean>
  6. ...
  7. </beans>

等效的 Java 注解配置为:

  1. @Bean(name = "multipartResolver")
  2. public CommonsMultipartResolver multipartResolver()
  3. {
  4. CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
  5. multipartResolver.setMaxUploadSize(20848820);
  6. return multipartResolver;
  7. }

3. 创建多部分上载 Rest API

创建给定的 REST API ,该 API 将负责处理发布到服务器的多个上载。 在给出的示例中,我在路径/employee-management/employees/1/photo/multiple处创建了 API。

我假设 ID 为'1'的员工存在于数据库中。 随时更改资源路径和实现。

EmployeeImageController.java

  1. package com.howtodoinjava.demo.controller;
  2. import static org.springframework.web.servlet
  3. .support.ServletUriComponentsBuilder.fromCurrentRequest;
  4. import java.io.File;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.io.OutputStream;
  9. import java.net.URI;
  10. import java.util.concurrent.Callable;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.beans.factory.annotation.Value;
  13. import org.springframework.context.annotation.PropertySource;
  14. import org.springframework.core.io.FileSystemResource;
  15. import org.springframework.core.io.Resource;
  16. import org.springframework.http.MediaType;
  17. import org.springframework.http.ResponseEntity;
  18. import org.springframework.util.FileCopyUtils;
  19. import org.springframework.web.bind.annotation.GetMapping;
  20. import org.springframework.web.bind.annotation.PathVariable;
  21. import org.springframework.web.bind.annotation.RequestMapping;
  22. import org.springframework.web.bind.annotation.RequestMethod;
  23. import org.springframework.web.bind.annotation.RequestParam;
  24. import org.springframework.web.bind.annotation.RestController;
  25. import org.springframework.web.multipart.MultipartFile;
  26. import com.howtodoinjava.demo.exception.RecordNotFoundException;
  27. import com.howtodoinjava.demo.model.Employee;
  28. import com.howtodoinjava.demo.repository.EmployeeRepository;
  29. @RestController
  30. @RequestMapping(value = "/employee-management/employees/{id}/photo")
  31. @PropertySource("classpath:application.properties")
  32. public class EmployeeImageController {
  33. @Autowired
  34. private EmployeeRepository repository;
  35. private File uploadDirRoot;
  36. @Autowired
  37. EmployeeImageController(@Value("${image.upload.dir}") String uploadDir,
  38. EmployeeRepository repository) {
  39. this.uploadDirRoot = new File(uploadDir);
  40. this.repository = repository;
  41. }
  42. @PostMapping(value = "/multiple", consumes = { "multipart/form-data" })
  43. Callable<ResponseEntity<?>> writeMultiple(@PathVariable Long id,
  44. @RequestParam("files") MultipartFile[] files) throws Exception
  45. {
  46. return () -> this.repository.findById(id).map(employee ->
  47. {
  48. Arrays.asList(files).stream().forEach(file ->
  49. {
  50. File fileForEmployee;
  51. try {
  52. fileForEmployee = uploadPath(employee, file);
  53. } catch (IOException e) {
  54. throw new RuntimeException(e);
  55. }
  56. try (InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(fileForEmployee)) {
  57. FileCopyUtils.copy(in, out);
  58. } catch (IOException ex) {
  59. throw new RuntimeException(ex);
  60. }
  61. });
  62. return ResponseEntity.ok().build();
  63. }).orElseThrow(() -> new RecordNotFoundException("Employee id is not present in database"));
  64. }
  65. private File uploadPath(Employee e, MultipartFile file) throws IOException
  66. {
  67. File uploadPath = Paths.get(this.uploadDirRoot.getPath(), e.getId().toString()).toFile();
  68. if(uploadPath.exists() == false) {
  69. uploadPath.mkdirs();
  70. }
  71. return new File(uploadPath.getAbsolutePath(), file.getOriginalFilename());
  72. }
  73. }

如果文件系统中尚不存在上述 REST 控制器,则会创建一个上载文件夹(名称为员工 ID)。 仍然需要定义以下属性。

application.properties

  1. image.upload.dir=c:/temp/images

同样,控制器返回可调用的 ,这意味着该方法将在 IO 操作可能运行时立即返回。 上传过程完成后,API 将返回响应。 要启用异步支持,请在DispatcherServlet中配置异步支持的

web.xml

  1. <web-app>
  2. <display-name>Employee Management REST APIs</display-name>
  3. <servlet>
  4. <servlet-name>rest</servlet-name>
  5. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  6. <load-on-startup>1</load-on-startup>
  7. <async-supported>true</async-supported>
  8. </servlet>
  9. <servlet-mapping>
  10. <servlet-name>rest</servlet-name>
  11. <url-pattern>/api/rest/*</url-pattern>
  12. </servlet-mapping>
  13. </web-app>

4. 多部分上传请求演示

出于演示目的,我创建了一个 JSP 页面,其中仅包含文件类型的多个字段。 我们将从计算机浏览一些图像,并将其上传到服务器。

multipleFileUpload.jsp

  1. <html>
  2. <head>
  3. <title>Spring REST File Upload</title>
  4. </head>
  5. <body>
  6. <form method="POST" action="/SpringRestExample/api/rest/employee-management/employees/1/photo/multiple"
  7. enctype="multipart/form-data">
  8. <table>
  9. <tr>
  10. <td>Select first file to upload</td>
  11. <td><input type="file" name="files" /></td>
  12. </tr>
  13. <tr>
  14. <td>Select second file to upload</td>
  15. <td><input type="file" name="files" /></td>
  16. </tr>
  17. <tr>
  18. <td>Select third file to upload</td>
  19. <td><input type="file" name="files" /></td>
  20. </tr>
  21. <tr>
  22. <td><input type="submit" value="Submit" /></td>
  23. </tr>
  24. </table>
  25. </form>
  26. </body>
  27. </html>

现在启动服务器并在 URL http://localhost:8080/SpringRestExample/multipleFileUpload.jsp中打开上传页面。 浏览图像,然后单击提交按钮。 图像文件将被上传到配置的上传目录中的服务器。

要下载文件,请在浏览器中输入 URL /employee-management/employees/1/photo,然后将显示图像。 下载 API 已包含在附件中。

请问您有关创建 Spring MVC REST API 来处理文件(例如图像)的多个上传问题。

下载源码

学习愉快!