天天看點

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

作者:JU幫

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

在後續第二到第四篇文章中,我們介紹了如何通過 HTML 頁面、HTTP 工具、Spring RestTemplate 發送檔案上傳的請求。但是發送的這些請求除了檔案之外的其他字段使用的是簡單的 K-V 值,下面我們介紹,檔案上傳如何發送和接收複雜的資料類型,如 JSON、XML 等。

建立接收檔案上傳請求的 Controller

該 Controller 和《SpringBoot 檔案上傳和下載下傳(二)》示例中的 Controller 的差別有兩點:

  1. 就是将除 MultipartFile 參數以外的其他參數封裝到 UploadFileRequestVO 實體中,并将該實體作為本示例 Controller 的入參
  2. UploadFileRequestVO 實體參數使用 @RequestPart 注解辨別
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class UploadFileRequestVO implements Serializable {

    /**
     * 檔案描述資訊
     */
    private String fileDesc;

    /**
     * 檔案過期時間
     */
    private String expirationTime;
}           
@Slf4j
@RestController
public class UploadFileController {

    // 本示例中的上傳檔案方法
    @PostMapping("/test/upload2/file")
    public String upload2(@RequestPart UploadFileRequestVO requestVO,
                          @RequestParam MultipartFile fileContent) {
        log.info("檔案上傳資訊:requestVO={}; fileName={}", requestVO, 
                 fileContent.getOriginalFilename());
        return "SUCCESS";
    }

    // 《SpringBoot 檔案上傳和下載下傳(二)》示例中的 Controller 上傳檔案方法
    @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";
    }
}           

建立測試代碼

本示例使用 RestTemplate 發送請求,代碼如下:

@Slf4j
@SpringBootTest
class UploadFileTest {

    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void testUpload2() {
        final String url = "http://127.0.0.1:8080/test/upload2/file";
        final String filePath = "C:\\Users\\jxrt\\Desktop\\upload-files\\txt-test-file.txt";
        File file = new File(filePath);

        MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
        bodyBuilder.part("fileExtInfo", new UploadFileRequestVO("檔案描述資訊", "2023-12-25"), 
                         MediaType.APPLICATION_JSON);
        bodyBuilder.part("fileContent", new ByteArrayResource(FileUtil.readBytes(file)), 
                         MediaType.APPLICATION_OCTET_STREAM).filename(file.getName());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        HttpEntity<MultiValueMap<String, HttpEntity<?>>> requestEntity = 
          new HttpEntity<>(bodyBuilder.build(), headers);
        ResponseEntity<String> responseEntity = 
          restTemplate.postForEntity(url, requestEntity, String.class);
        log.info("響應資訊:{}", responseEntity.getBody());
    }
}           

本示例中的測試代碼與《SpringBoot 檔案上傳和下載下傳(四)》中的測試代碼差別如下:

  1. 使用 UploadFileRequestVO 執行個體作為 fileExtInfo 參數的值
  2. fileExtInfo 參數的 Content-Type 為 application/json,因為我們需要将該對象序列化為 JSON 字元串

啟動服務,執行測試代碼,可以正常發送和接收,輸出結果如下:

檔案上傳資訊:fileExtInfo=UploadFileRequestVO(fileDesc=檔案描述資訊, expirationTime=2023-12-25); fileName=txt-test-file.txt

@RequestBody & @RequestParam & @RequestPart

Spring 提供綁定請求參數和對應 Controller 方法參數映射的注解有三個,分别為:@RequestBody、@RequestParam、@RequestPart,下面我們介紹一下這三個注解的使用場景和差別。

HTTP 請求方式以我們最常用的 GET 和 POST 請求為例。
  • @RequestParam

@RequestBody 用來處理 Content-Type 為 application/x-www-form-urlencoded 編碼的内容(Http協定中,如果不指定Content-Type,則預設傳遞的參數就是application/x-www-form-urlencoded類型),也就是我們常用的 Query 參數拼接,例如:?name=張三&age=12

通常我們用于接收 GET 請求參數或 POST 簡單的 String 類型的值。

  • @RequestBody

處理 HttpEntity 傳遞過來的資料,一般用來處理非 Content-Type 為 application/x-www-form-urlencoded 編碼格式的資料。可以處理 application/json 或者是 application/xml 等,一般情況下來說常用其來處理 application/json 類型。

在 GET 請求中,因為沒有 HttpEntity,是以 @RequestBody 并不适用。

通常用于接收 POST Json 類型的值。

  • @RequestPart

@RequestPart 這個注解用在 Content-Type 為 multipart/form-data 表單送出請求的方法上。可以接收送出的任何類型資料(檔案流、String 類型的值、Json 等複雜類型的值)。

@RequestParam 也同樣支援 multipart/form-data 請求,但是隻能用于接收檔案流和 String 類型的值。

是以在上面執行個體中使用 @RequestPart 接收 Json 類型的資料映射到 UploadFileRequestVO 執行個體,建議如果 Content-Type 為 multipart/form-data 表單,使用 @RequestPart 接收參數。

檔案下載下傳内容見下一篇文章,如果文章對大家有所幫助,歡迎點贊、關注、評論。

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

上一篇:SpringBoot 檔案上傳和下載下傳(四)