知識庫 / Spring / Spring MVC RSS 訂閱

使用 Spring MVC 下載圖片或文件

Spring MVC
HongKong
10
02:38 PM · Dec 06 ,2025

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

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.