天天看點

SpringBoot 檔案上傳和下載下傳(二)

作者:JU幫

在上一篇文章《SpringBoot 檔案上傳和下載下傳(一)》中,我們簡紹了 HTTP 中關于 MIME 類型、HTTP Header Content-Type 和 Content-Disposition 的内容。

在本篇和後續篇章中正式開始學習一下 SpringBoot 中檔案上傳的知識,測試的場景分為三類:

  • 通過 HTML 頁面上傳檔案
  • 通過 Jmeter、Postman、IDEA HTTP Client 工具上傳
  • 通過 SpringBoot 服務上傳

本篇學習如何通過 HTML 頁面上傳檔案

建立 HTML 頁面

我們先簡單寫一個用于上傳檔案的 HTML 頁面,效果如下:

SpringBoot 檔案上傳和下載下傳(二)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>測試檔案上傳</title>
  <style>
    div {
      padding: 5px;
    }
  </style>
</head>
<body>
<form method="post" action="http://127.0.0.1:8080/test/upload/file" enctype="multipart/form-data">
  <div><label>檔案描述:<input type="text" name="fileDesc"></label></div>
  <div><label>過期時間:<input type="date" name="expirationTime"></label></div>
  <div><label>選擇檔案:<input type="file" name="fileContent"></label></div>
  <div><input type="submit" value="送出資訊"></div>
</form>
</body>
</html>           

建立 SpringBoot 微服務

建立 SpringBoot 微服務,建立用于測試檔案上傳的 Controller,如下所示:

@Slf4j
@RestController
public class UploadFileController {

    @PostMapping("/test/upload/file")
    public String upload(@RequestParam String fileDesc, @RequestParam String expirationTime,
                         @RequestParam MultipartFile fileContent) {
        log.info("檔案上傳資訊:fileDesc={}; expirationTime={}; fileName={}", fileDesc,
                expirationTime, fileContent.getOriginalFilename());
        return "SUCCESS";
    }
}           

SpringBoot 配置使用預設,即端口号為 8080

填寫表單,發送請求

填寫 HTML 頁面表單如下所示:

SpringBoot 檔案上傳和下載下傳(二)

點選 “送出資訊” 按鈕,發送請求到伺服器,伺服器輸出日志結果如下所示:

檔案上傳資訊:fileDesc=檔案描述資訊; expirationTime=2023-03-08; fileName=image-test-file.png

結果分析

就上面的簡單示例,我們分析一下檔案是如何上傳的,SpringBoot 服務是如何接收的:

  1. HTML 中 form 表單屬性值注意點
  • 如果表單包括了檔案上傳,enctype 必須設定為 multipart/form-data,在文章《SpringBoot 檔案上傳和下載下傳(一)》中簡紹 multipart/form-data 是一種複合 MIME 類型,可以在一次請求中,包含多種單一 MIME 類型。在本次示例中,包括兩種 MIME 單一類型:① fileDesc 和 expirationTime 是文本類型(text/plain)② 檔案對應的具體類型(image/jpeg)或位元組流類型(application/octet-stream),具體在分析 multipart/form-data 請求封包時可以看到。
  • 如果設定 enctype 值,這 form method 必須為 post
  1. Controller 中的注意點
  • 在本次示例中,HTTP 請求中參數與方法同名參數映射采用的注解是 @RequestParam(對于 HTML 通過 form 表單發送簡單參數可以使用,後面我們會看到使用 @RequestPart 注解,具體兩個注解的差別後面簡紹)。
  • 對于接收檔案流,可以使用 Spring 提供的 org.springframework.web.multipart.MultipartFile 類,Spring 會将 multipart/form-data 請求中檔案資訊封裝到 MultipartFile 類的執行個體中。
  1. 檢視 HTML 發送的請求封包
SpringBoot 檔案上傳和下載下傳(二)
  • 請求消息頭中,我們可以看到 Content-Type 為 multipart/form-data; boundary=xxxxx,其中 boundary 定義了請消息體中,每部分的分隔字元串
  • 請求消息體中,我們可以看到有與 HTML 三個字段相對應的三部分資料,各部分資料之間使用 boundary 字元串分隔。這三部分資料分為兩類:① 第一部分和第二部分為普通字元串,Content-Disposition 值為 form-data; name="字段名",後面為空行和該字段對應的值,雖然沒有設定 Content-Type,其實預設為 text/plain;② 第三部分為上傳的檔案資訊,Content-Disposition 值為 form-data; name="字段名"; filename="檔案名稱",後面是空行和上傳的檔案資料(浏覽器做了優化,不顯示檔案資料),Content-Type 值為 text/plain(因為我們測試的檔案為 txt 檔案)。(請求資訊中就包括了 Content-Disposition 在 multipart/form-data 請求中的使用場景,在文章《SpringBoot 檔案上傳和下載下傳(一)》有說明)

通過 HTTP 工具發送檔案上傳相關内容見下一篇文章,如果文章對大家有所幫助,歡迎點贊、關注、評論。

SpringBoot 檔案上傳和下載下傳(二)