企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# Spring REST – 多部分上传和下载示例 > 原文: [https://howtodoinjava.com/spring-restful/multipart-upload-download-example/](https://howtodoinjava.com/spring-restful/multipart-upload-download-example/) 了解如何使用接受[`MultipartFile`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html)请求的 Spring REST API **上传多部分**二进制文件(例如 jpeg 图像)。 还学习使用[`FileSystemResource`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/FileSystemResource.html)使用另一个 REST API 下载文件。 ## 1\. Maven 依赖 除了 spring webmvc 之外,我们在类路径中还需要[`commons-fileupload`](https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload)和[`commons-io`](https://mvnrepository.com/artifact/commons-io/commons-io)。 `pom.xml` ```java 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`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/commons/CommonsMultipartResolver.html)实现。 它提供`maxUploadSize`,`maxInMemorySize`和`defaultEncoding`设置作为 bean 属性。 此类的目的是将临时文件保存到 [Servlet](https://howtodoinjava.com/servlets/complete-java-servlets-tutorial/) 容器的临时目录中。 `rest-servlet.xml` ```java <beans> ... <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="100000"/> </bean> ... </beans> ``` ## 3\. 创建多部分处理器 API 创建两个 [REST API](http://restfulapi.net/) ,它们将负责处理上载和下载请求以及响应。 在给出的示例中,我在路径`/employee-management/employees/1/photo`处创建了 API。 我假设 ID 为`'1'`的员工存在于数据库中。 随时更改资源路径和实现。 `EmployeeImageController.java` ```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; } @GetMapping ResponseEntity<Resource> read(@PathVariable Long id) { return this.repository.findById(id) .map(employee -> { File file = fileFor(employee); Resource fileSystemResource = new FileSystemResource(file); return ResponseEntity.ok() .contentType(MediaType.IMAGE_JPEG) .body(fileSystemResource); }) .orElseThrow(() -> new RecordNotFoundException("Image for available")); } @RequestMapping(method = { RequestMethod.POST, RequestMethod.PUT }, consumes = { "multipart/form-data" }) Callable<ResponseEntity<?>> write(@PathVariable Long id, @RequestParam("file") MultipartFile file) throws Exception { return () -> this.repository.findById(id) .map(employee -> { File fileForEmployee = fileFor(employee); try (InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(fileForEmployee)) { FileCopyUtils.copy(in, out); } catch (IOException ex) { throw new RuntimeException(ex); } URI location = fromCurrentRequest().buildAndExpand(id).toUri(); return ResponseEntity.created(location).build(); }) .orElseThrow(() -> new RecordNotFoundException("Employee id is not present in database")); } private File fileFor(Employee e) { return new File(this.uploadDirRoot, Long.toString(e.getId())); } } ``` 上面的 REST 控制器依赖于**上传文件夹**即`image.upload.dir`配置在属性文件中的存在。 `application.properties` ```java image.upload.dir=c:/temp/images ``` 同样,控制器返回可调用的 **[](https://howtodoinjava.com/java/multi-threading/java-callable-future-example/)**,这意味着该方法将在 IO 操作可能运行时立即返回。 上传过程完成后,API 将返回响应。 要**启用异步支持**,请在[`DispatcherServlet`](https://howtodoinjava.com/spring5/webmvc/spring-dispatcherservlet-tutorial/)中配置**异步支持的**。 `web.xml` ```java <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 页面,其中仅包含一个类型的文件字段。 我们将从计算机浏览图像,并将其上传到服务器。 `singleFileUpload.jsp` ```java <html> <head> <title>Spring REST File Upload</title> </head> <body> <form method="POST" action="/SpringRestExample/api/rest/employee-management/employees/1/photo" enctype="multipart/form-data"> <table> <tr> <td>Select a file to upload</td> <td><input type="file" name="file" /></td> </tr> <tr> <td><input type="submit" value="Submit" /></td> </tr> </table> </form> </body> </html> ``` 现在启动服务器并在 URL `http://localhost:8080/SpringRestExample/singleFileUpload.jsp`中打开上传页面。 浏览文件,然后单击提交按钮。 图像文件将被上传到配置的上传目录中的服务器。 要下载文件,请在浏览器中输入 URL `/employee-management/employees/1/photo`,然后将显示图像。 请问您有关创建 **Spring MVC REST API 来处理多部分文件上传和下载**的问题。 [下载源码](https://howtodoinjava.com/wp-content/downloads/SpringRestMultiPartExample.zip) 学习愉快!