一、創(chuàng)建應(yīng)用程序類
要啟動Spring Boot MVC應(yīng)用程序,首先需要一個(gè)啟動器。在這個(gè)示例中,已經(jīng)添加了spring-boot-starter thymelaf和spring-boot-starter web作為依賴項(xiàng)。要使用Servlet容器上傳文件,您需要注冊一個(gè)MultipartConfigElement類(在web.xml中為<multipart-config>)。多虧了Spring Boot,一切都可以自動配置!
1、引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、創(chuàng)建UploadingFilesApplication
開始使用此應(yīng)用程序所需的只是以下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);
}
}
二、創(chuàng)建文件上傳控制器
最初的應(yīng)用程序已經(jīng)包含了一些類來處理在磁盤上存儲和加載上傳的文件。它們都位于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 ResponseEntity<Resource> serveFile(@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進(jìn)行注釋,以便Spring MVC可以拾取它并查找路由。每個(gè)方法都用@GetMapping或@PostMapping標(biāo)記,以將路徑和HTTP操作與特定的控制器操作聯(lián)系起來。
在這種情況下:
-
GET/:從StorageService查找當(dāng)前上載文件的列表,并將其加載到Thymelaf模板中。它使用MvcUriComponentsBuilder計(jì)算到實(shí)際資源的鏈接。
-
GET/files/{filename}:加載資源(如果存在),并使用Content-Disposition響應(yīng)標(biāo)頭將其發(fā)送到瀏覽器進(jìn)行下載。
-
POST/:處理由多部分組成的消息文件,并將其提供給StorageService進(jìn)行保存。
您需要提供StorageService,以便控制器可以與存儲層(如文件系統(tǒng))進(jìn)行交互。以下列表(來自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);
Stream<Path> loadAll();
Path load(String filename);
Resource loadAsResource(String filename);
void deleteAll();
}
三、創(chuàng)建 HTML 模板
以下Thymelaf模板(來自src/main/resources/templates/uploadForm.html)顯示了如何上傳文件并顯示已上傳內(nèi)容的示例:
<html xmlns:th="https://www.thymeleaf.org">
<body>
<div th:if="${message}">
<h2 th:text="${message}"/>
</div>
<div>
<form method="POST" enctype="multipart/form-data" action="/">
<table>
<tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
<tr><td></td><td><input type="submit" value="Upload" /></td></tr>
</table>
</form>
</div>
<div>
<ul>
<li th:each="file : ${files}">
<a th:href="${file}" th:text="${file}" />
</li>
</ul>
</div>
</body>
</html>
此模板由三部分組成:
-
頂部的一個(gè)可選消息,Spring MVC在其中寫入一個(gè)flash范圍的消息。
-
允許用戶上傳文件的表單。
-
從后端提供的文件列表。
四、調(diào)整文件上傳限制
配置文件上載時(shí),設(shè)置文件大小限制通常很有用。想象一下,試圖處理5GB的文件上傳!使用Spring Boot,我們可以通過一些屬性設(shè)置來調(diào)整其自動配置的MultipartConfigElement。
將以下財(cái)產(chǎn)添加到現(xiàn)有財(cái)產(chǎn)設(shè)置中(在src/main/resources/application.nenenebc屬性中):
spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB
多部分設(shè)置的約束如下:
-
spring.servlet.multipart.max-file-size設(shè)置為 128KB,表示總文件大小不能超過 128KB。
-
spring.servlet.multipart.max-request-size設(shè)置為 128KB,這意味著 的總請求大小不能超過 128KB。multipart/form-data
五、運(yùn)行應(yīng)用程序
您想要一個(gè)上傳文件的目標(biāo)文件夾,因此需要增強(qiáng)Spring Initializer創(chuàng)建的基本UploadingFilesApplication類,并添加Boot CommandLineRunner以在啟動時(shí)刪除并重新創(chuàng)建該文件夾。以下列表(來自src/main/java.com/example/uploadingfiles/UploadingFilesApplication.java)顯示了如何做到這一點(diǎn):
package com.example.uploadingfiles;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import com.example.uploadingfiles.storage.StorageProperties;
import com.example.uploadingfiles.storage.StorageService;
@SpringBootApplication
@EnableConfigurationProperties(StorageProperties.class)
public class UploadingFilesApplication {
public static void main(String[] args) {
SpringApplication.run(UploadingFilesApplication.class, args);
}
@Bean
CommandLineRunner init(StorageService storageService) {
return (args) -> {
storageService.deleteAll();
storageService.init();
};
}
}
@SpringBootApplication是一個(gè)方便的注釋,它添加了以下所有內(nèi)容:
@配置:將類標(biāo)記為應(yīng)用程序上下文的bean定義的源。
@EnableAutoConfiguration:告訴SpringBoot開始基于類路徑設(shè)置、其他bean和各種屬性設(shè)置添加bean。例如,如果spring-webmvc在類路徑上,則此注釋將應(yīng)用程序標(biāo)記為web應(yīng)用程序并激活關(guān)鍵行為,例如設(shè)置DispatcherServlet。
@ComponentScan:告訴Spring在com/example包中查找其他組件、配置和服務(wù),讓它找到控制器。
main()方法使用Spring Boot的SpringApplication.run()方法來啟動應(yīng)用程序。您注意到?jīng)]有一行XML嗎?也沒有web.xml文件。這個(gè)web應(yīng)用程序是100%純Java的,您不需要配置任何管道或基礎(chǔ)設(shè)施。
六、測試
有多種方法可以在我們的應(yīng)用程序中測試這一特定功能。下面的列表(來自src/test/java.com/example/uploadingfiles/FileUploadTests.java)顯示了一個(gè)使用MockMvc的示例,這樣就不需要啟動servlet容器:文章來源:http://www.zghlxwxcb.cn/news/detail-622095.html
package com.example.uploadingfiles;
import java.nio.file.Paths;
import java.util.stream.Stream;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.example.uploadingfiles.storage.StorageFileNotFoundException;
import com.example.uploadingfiles.storage.StorageService;
@AutoConfigureMockMvc
@SpringBootTest
public class FileUploadTests {
@Autowired
private MockMvc mvc;
@MockBean
private StorageService storageService;
@Test
public void shouldListAllFiles() throws Exception {
given(this.storageService.loadAll())
.willReturn(Stream.of(Paths.get("first.txt"), Paths.get("second.txt")));
this.mvc.perform(get("/")).andExpect(status().isOk())
.andExpect(model().attribute("files",
Matchers.contains("http://localhost/files/first.txt",
"http://localhost/files/second.txt")));
}
@Test
public void shouldSaveUploadedFile() throws Exception {
MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt",
"text/plain", "Spring Framework".getBytes());
this.mvc.perform(multipart("/").file(multipartFile))
.andExpect(status().isFound())
.andExpect(header().string("Location", "/"));
then(this.storageService).should().store(multipartFile);
}
@SuppressWarnings("unchecked")
@Test
public void should404WhenMissingFile() throws Exception {
given(this.storageService.loadAsResource("test.txt"))
.willThrow(StorageFileNotFoundException.class);
this.mvc.perform(get("/files/test.txt")).andExpect(status().isNotFound());
}
}
?文章來源地址http://www.zghlxwxcb.cn/news/detail-622095.html
到了這里,關(guān)于Spring Mvc 文件上傳(MultipartFile )—官方原版的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!