1. 概述
向客户端提供靜態文件可以通過多種方式實現,使用 Spring Controller 並非總是最佳選擇。
然而,在某些情況下,控制器路由是必要的——而本文將重點關注這一點。
2. Maven 依賴
首先,我們需要將依賴項添加到我們的 pom.xml 中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>以上內容就完成了,這裏不需要任何其他信息。有關版本信息,請訪問 Maven Central。
3. 使用 @ResponseBody 標註
使用 @ResponseBody 標註於控制器方法,指示方法返回的對象應直接序列化到 HTTP 響應體,是一種直接的解決方案。
@GetMapping("/get-text")
public @ResponseBody String getText() {
return "Hello world";
}
因此,這種方法只會返回字符串 Hello world,而不是返回一個名稱為 Hello world 的視圖,就像一個典型的 MVC 應用程序。
使用 @ResponseBody,我們可以返回幾乎任何媒體類型,只要我們有相應的 HTTP Message 轉換器來處理和將它們映射到輸出流。
4. 使用 產生 用於返回圖像
返回字節數組允許我們返回幾乎任何內容——例如圖像或文件:
@GetMapping(value = "/image")
public @ResponseBody byte[] getImage() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/image.jpg");
return IOUtils.toByteArray(in);
}
在這裏,我們並沒有定義返回的字節數組是圖像。因此,客户端將無法將其作為圖像處理,而且瀏覽器很可能只會顯示圖像的實際字節。
為了定義返回的字節數組對應於圖像,我們可以將 produces 屬性設置為 @GetMapping 註解,從而精確指定返回對象的 MIME 類型。
@GetMapping(
value = "/get-image-with-media-type",
produces = MediaType.IMAGE_JPEG_VALUE
)
public @ResponseBody byte[] getImageWithMediaType() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/image.jpg");
return IOUtils.toByteArray(in);
}
此處produces設置為MediaType.IMAGE_JPEG_VALUE,以指示返回的對象必須作為 JPEG 圖像進行處理。
現在,瀏覽器將識別並正確顯示響應體作為圖像。
5. 使用 produces 返回原始數據
參數 produces 可以設置為多種不同的值(完整的列表可以在 這裏 找到),具體取決於我們想要返回的對象的類型。
因此,如果我們要返回一個原始文件,我們可以簡單地使用 APPLICATION_OCTET_STREAM_VALUE:
@GetMapping(
value = "/get-file",
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
)
public @ResponseBody byte[] getFile() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/data.txt");
return IOUtils.toByteArray(in);
}
或者,我們可以返回一個 ByteArrayResource 而不是字節數組:
@GetMapping(value = "/get-file-via-byte-array-resource", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public @ResponseBody Resource getFileViaByteArrayResource() throws IOException, URISyntaxException {
Path path = Paths.get(getClass().getResource("/com/baeldung/produceimage/data.txt").toURI());
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));
return resource;
}Resource 類是 Spring 提供的抽象層級,它允許我們編寫通用的、靈活的代碼,能夠處理來自各種來源的資源。 使用Resource 而不是InputStream 具有以下優勢:
- Resource 提供有關資源的額外元數據。
- 它可以與其他的 Spring 抽象一起使用。
- 更容易進行模擬。
6. 動態設置 contentType
我們將瞭解如何動態地設置響應的內容類型。在這種情況下,我們不能使用 produces 參數,因為它期望一個常量。我們需要直接設置 ResponseEntity 的 contentType :
@GetMapping("/get-image-dynamic-type")
@ResponseBody
public ResponseEntity<InputStreamResource> getImageDynamicType(@RequestParam("jpg") boolean jpg) {
MediaType contentType = jpg ? MediaType.IMAGE_JPEG : MediaType.IMAGE_PNG;
InputStream in = jpg ?
getClass().getResourceAsStream("/com/baeldung/produceimage/image.jpg") :
getClass().getResourceAsStream("/com/baeldung/produceimage/image.png");
return ResponseEntity.ok()
.contentType(contentType)
.body(new InputStreamResource(in));
}我們決定根據查詢參數設置返回圖像的內容類型。
7. 結論
在本文中,我們探討了一個簡單的示例——從 Spring 控制器返回圖像或文件。我們重點介紹了各種可能的響應類型,例如 String、字節數組和 Resource。