原文: https://howtodoinjava.com/spring-restful/multipart-multiple-uploads-example/
了解如何使用 Spring REST API 接受上传多个多部分二进制文件(例如 jpeg 图像),这些文件接受MultipartFile
请求的数组。
1. Maven 依赖
除了 spring webmvc 之外,我们还将在类路径中需要commons-fileupload
和commons-io
。
pom.xml
dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
2. 配置CommonsMultipartResolver
它是commons-fileupload
的基于 Servlet 的MultipartResolver
实现。 它提供maxUploadSize
,maxInMemorySize
和defaultEncoding
设置作为 bean 属性。
此类的目的是将临时文件保存到 Servlet 容器的临时目录中。
rest-servlet.xml
<beans>
...
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1000000"/>
</bean>
...
</beans>
等效的 Java 注解配置为:
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver()
{
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(20848820);
return multipartResolver;
}
3. 创建多部分上载 Rest API
创建给定的 REST API ,该 API 将负责处理发布到服务器的多个上载。 在给出的示例中,我在路径/employee-management/employees/1/photo/multiple
处创建了 API。
我假设 ID 为'1'
的员工存在于数据库中。 随时更改资源路径和实现。
EmployeeImageController.java
package com.howtodoinjava.demo.controller;
import static org.springframework.web.servlet
.support.ServletUriComponentsBuilder.fromCurrentRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.concurrent.Callable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.howtodoinjava.demo.exception.RecordNotFoundException;
import com.howtodoinjava.demo.model.Employee;
import com.howtodoinjava.demo.repository.EmployeeRepository;
@RestController
@RequestMapping(value = "/employee-management/employees/{id}/photo")
@PropertySource("classpath:application.properties")
public class EmployeeImageController {
@Autowired
private EmployeeRepository repository;
private File uploadDirRoot;
@Autowired
EmployeeImageController(@Value("${image.upload.dir}") String uploadDir,
EmployeeRepository repository) {
this.uploadDirRoot = new File(uploadDir);
this.repository = repository;
}
@PostMapping(value = "/multiple", consumes = { "multipart/form-data" })
Callable<ResponseEntity<?>> writeMultiple(@PathVariable Long id,
@RequestParam("files") MultipartFile[] files) throws Exception
{
return () -> this.repository.findById(id).map(employee ->
{
Arrays.asList(files).stream().forEach(file ->
{
File fileForEmployee;
try {
fileForEmployee = uploadPath(employee, file);
} catch (IOException e) {
throw new RuntimeException(e);
}
try (InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(fileForEmployee)) {
FileCopyUtils.copy(in, out);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
});
return ResponseEntity.ok().build();
}).orElseThrow(() -> new RecordNotFoundException("Employee id is not present in database"));
}
private File uploadPath(Employee e, MultipartFile file) throws IOException
{
File uploadPath = Paths.get(this.uploadDirRoot.getPath(), e.getId().toString()).toFile();
if(uploadPath.exists() == false) {
uploadPath.mkdirs();
}
return new File(uploadPath.getAbsolutePath(), file.getOriginalFilename());
}
}
如果文件系统中尚不存在上述 REST 控制器,则会创建一个上载文件夹(名称为员工 ID)。 仍然需要定义以下属性。
application.properties
image.upload.dir=c:/temp/images
同样,控制器返回可调用的 ,这意味着该方法将在 IO 操作可能运行时立即返回。 上传过程完成后,API 将返回响应。 要启用异步支持,请在DispatcherServlet
中配置异步支持的。
web.xml
<web-app>
<display-name>Employee Management REST APIs</display-name>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/api/rest/*</url-pattern>
</servlet-mapping>
</web-app>
4. 多部分上传请求演示
出于演示目的,我创建了一个 JSP 页面,其中仅包含文件类型的多个字段。 我们将从计算机浏览一些图像,并将其上传到服务器。
multipleFileUpload.jsp
<html>
<head>
<title>Spring REST File Upload</title>
</head>
<body>
<form method="POST" action="/SpringRestExample/api/rest/employee-management/employees/1/photo/multiple"
enctype="multipart/form-data">
<table>
<tr>
<td>Select first file to upload</td>
<td><input type="file" name="files" /></td>
</tr>
<tr>
<td>Select second file to upload</td>
<td><input type="file" name="files" /></td>
</tr>
<tr>
<td>Select third file to upload</td>
<td><input type="file" name="files" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>
</body>
</html>
现在启动服务器并在 URL http://localhost:8080/SpringRestExample/multipleFileUpload.jsp
中打开上传页面。 浏览图像,然后单击提交按钮。 图像文件将被上传到配置的上传目录中的服务器。
要下载文件,请在浏览器中输入 URL /employee-management/employees/1/photo
,然后将显示图像。 下载 API 已包含在附件中。
请问您有关创建 Spring MVC REST API 来处理文件(例如图像)的多个上传问题。
学习愉快!