Spring认证指南:了解如何构建一个多文件上传的 Spring 应用程序
本攻略将引导您完结创立能够接纳 HTTP 多部分文件上传的服务器应用程序的进程。
你将制作什么
您将创立一个承受文件上传的 Spring Boot Web 应用程序。您还将构建一个简单的 HTML 界面来上传测验文件。
你需求什么
- 约15分钟
- 最喜欢的文本编辑器或 IDE
- JDK 1.8或更高版本
- Gradle 4+或Maven 3.2+
- 您还能够将代码直接导入 IDE:弹簧工具套件 (STS)IntelliJ IDEA
怎么完结本攻略
像大多数 Spring入门攻略一样,您能够从头开端并完结每个进程,也能够绕过您现已了解的基本设置进程。不管哪种办法,您终究都会得到作业代码。
要从头开端,请持续从 Spring Initializr 开端。
要越过基础知识,请履行以下操作:
- 下载并解压本攻略的源代码库,或运用Git克隆它:git clone https://github.com/spring-guides/gs-uploading-files.git
- 光盘进入gs-uploading-files/initial
- 持续创立应用程序类。
完结后,您能够对照中的代码检查成果
gs-uploading-files/complete。
从 Spring Initializr 开端
您能够运用这个预先初始化的项目并单击 Generate 下载 ZIP 文件。此项目装备为适合本教程中的示例。
手动初始化项目:
- 导航到https://start.spring.io。该服务提取应用程序所需的一切依靠项,并为您完结大部分设置。
- 挑选 Gradle 或 Maven 以及您要运用的言语。本攻略假定您挑选了 Java。
- 单击Dependencies并挑选Spring Web和Thymeleaf。
- 单击生成。
- 下载生成的 ZIP 文件,该文件是依据您的挑选装备的 Web 应用程序的存档。
假如您的 IDE 具有 Spring Initializr 集成,您能够从您的 IDE 完结此进程。
你也能够从 Github 上 fork 项目并在你的 IDE 或其他编辑器中翻开它。
创立应用程序类
要发动 Spring Boot MVC 应用程序,首要需求一个发动器。在此示例中,
spring-boot-starter-thymeleaf并且spring-boot-starter-web已作为依靠项增加。要运用 Servlet 容器上传文件,您需求注册一个MultipartConfigElement类(在 web.xml 中)。感谢 Spring Boot,一切都是为您主动装备的!
开端运用此应用程序所需的只是以下UploadingFilesApplication类(来自
src/main/java/com/example/uploadingfiles/UploadingFilesApplication.java):
package com.example.uploadingfiles; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class UploadingFilesApplication { public static void main(String[] args) { SpringApplication.run(UploadingFilesApplication.class, args); } }
作为主动装备 Spring MVC 的一部分,Spring Boot 将创立一个MultipartConfigElementbean 并为文件上传做好准备。
创立文件上传控制器
初始应用程序现已包括一些类来处理在磁盘上存储和加载上传的文件。它们都坐落
com.example.uploadingfiles.storage包装中。您将在新的FileUploadController. 以下清单(来自
src/main/java/com/example/uploadingfiles/FileUploadController.java)显现了文件上传控制器:
package com.example.uploadingfiles; import java.io.IOException; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.example.uploadingfiles.storage.StorageFileNotFoundException; import com.example.uploadingfiles.storage.StorageService; @Controller public class FileUploadController { private final StorageService storageService; @Autowired public FileUploadController(StorageService storageService) { this.storageService = storageService; } @GetMapping("/") public String listUploadedFiles(Model model) throws IOException { model.addAttribute("files", storageService.loadAll().map( path -> MvcUriComponentsBuilder.fromMethodName(FileUploadController.class, "serveFile", path.getFileName().toString()).build().toUri().toString()) .collect(Collectors.toList())); return "uploadForm"; } @GetMapping("/files/{filename:.+}") @ResponseBody public ResponseEntityserveFile(@PathVariable String filename) { Resource file = storageService.loadAsResource(filename); return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file); } @PostMapping("/") public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { storageService.store(file); redirectAttributes.addFlashAttribute("message", "You successfully uploaded " + file.getOriginalFilename() + "!"); return "redirect:/"; } @ExceptionHandler(StorageFileNotFoundException.class) public ResponseEntity handleStorageFileNotFound(StorageFileNotFoundException exc) { return ResponseEntity.notFound().build(); } }
该类FileUploadController带有注释,@Controller以便 Spring MVC 能够拾取它并查找路由。每个办法都被标记@GetMapping或@PostMapping将途径和 HTTP 操作绑定到特定的控制器操作。
在这种情况下:
- GET /:从 中查找当前上传文件的列表StorageService并将其加载到 Thymeleaf 模板中。它经过运用 计算到实际资源的链接MvcUriComponentsBuilder。
- GET /files/{filename}:加载资源(假如存在)并运用Content-Disposition呼应头将其发送到浏览器进行下载。
- POST /:处理多部分音讯file并将其供给给StorageService保存。
在出产场景中,您更有可能将文件存储在暂时位置、数据库或 NoSQL 存储(例如Mongo 的 GridFS)中。最好不要在应用程序的文件体系中加载内容。
您将需求供给一个StorageService以便控制器能够与存储层(例如文件体系)进行交互。以下清单(来自
src/main/java/com/example/uploadingfiles/storage/StorageService.java)显现了该界面:
package com.example.uploadingfiles.storage; import org.springframework.core.io.Resource; import org.springframework.web.multipart.MultipartFile; import java.nio.file.Path; import java.util.stream.Stream; public interface StorageService { void init(); void store(MultipartFile file); StreamloadAll(); Path load(String filename); Resource loadAsResource(String filename); void deleteAll(); }
创立 HTML 模板
以下 Thymeleaf 模板(来自
src/main/resources/templates/uploadForm.html)显现了怎么上传文件并显现已上传内容的示例:
调整文件上传限制
装备文件上传时,设置文件巨细限制通常很有用。幻想一下尝试处理 5GB 文件上传!MultipartConfigElement运用 Spring Boot,咱们能够运用一些特点设置来调整它的主动装备。
将以下特点增加到现有特点设置(在 中
src/main/resources/application.properties):
- spring.servlet.multipart.max-file-size 设置为 128KB,这意味着总文件巨细不能超过 128KB。
- spring.servlet.multipart.max-request-size设置为 128KB,这意味着 a 的总恳求巨细multipart/form-data不能超过 128KB。
运转应用程序
@SpringBootApplication是一个方便的注释,它增加了以下一切内容:
- @Configuration: 将类标记为应用程序上下文的 bean 界说源。
- @EnableAutoConfiguration:告诉 Spring Boot 依据类途径设置、其他 bean 和各种特点设置开端增加 bean。例如,假如spring-webmvc坐落类途径上,则此注释将应用程序标记为 Web 应用程序并激活关键行为,例如设置DispatcherServlet.
- @ComponentScan: 告诉 Spring 在包中查找其他组件、装备和服务com/example,让它找到控制器。
构建一个可履行的 JAR
假如您运用 Gradle,则能够运用./gradlew bootRun. 或者,您能够运用构建 JAR 文件./gradlew build,然后运转 JAR 文件,如下所示:
假如您运用 Maven,则能够运用./mvnw spring-boot:run. 或者,您能够运用构建 JAR 文件,./mvnw clean package然后运转该 JAR 文件,如下所示:
此处描绘的进程创立了一个可运转的 JAR。您还能够构建经典的 WAR 文件。
它运转接纳文件上传的服务器端部分。显现记录输出。该服务应在几秒钟内发动并运转。
测验您的应用程序
在这些测验中,您运用各种模拟来设置与您的控制器以及StorageService与 Servlet 容器本身的交互,运用MockMultipartFile.
有关集成测验的示例,请参见
FileUploadIntegrationTests类(坐落 中
src/test/java/com/example/uploadingfiles)。