簡體   English   中英

如何修復 Spring 引導分段上傳中的“所需請求部分不存在”

[英]How to fix "Required request part is not present" in a Spring Boot multipart upload

雖然我的問題與類似,但我沒有使用MockMultipartFile 這是我的用例。

在 Spring Boot 2.4.5 應用程序中,我編寫了一個執行代碼的單元測試,它應該發送一個multipart/form-data請求。 為了能夠從測試中測試接收端,我啟動了一個Controller作為multipart/form-data調用的接收器。 這是 controller(它目前沒有對參數做任何事情)。

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/v1/api")
public class VideoServiceStub {
    @PostMapping(value ="/videoservice/videos", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity<String> upload(@RequestPart("name") MultipartFile name, @RequestPart("file") MultipartFile file) {
        return ResponseEntity.status(HttpStatus.OK).body("it works");
    }
}

我的用例的特別之處在於 POST 應由內存中的字節數組InputStream制成。 為了提供一些上下文,我的代碼稍后將從 URL 下載一個文件,並使這個multipart/form-data中繼數據並將其發送到其他地方。 單元測試將觸發以下代碼執行,該代碼使用 Spring Rest 模板。

protected void sendToVideoService(String name, byte[] content) {
        var headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        var body = new LinkedMultiValueMap<>();
        body.add("name", name);
        body.add("file", new ByteArrayResource(content));

        var url = this.uploadUrl();  // the test will return the correct localhost URL here

        var requestEntity = new HttpEntity<>(body, headers);
        restTemplate.postForEntity(url, requestEntity, String.class);        
    }

它以HttpClientErrorException$BadRequest失敗,我可以在標准輸出日志中看到:

2021-06-01 07:23:33.027  WARN 27432 --- [o-auto-1-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'name' is not present]

為了驗證問題出在接收端,我使用較新的java.net.http.HttpClient和出色的甲醇庫測試了一個版本。

protected void sendToVideoServiceUsingJava11(String name, byte[] content) {
    var url = this.uploadUrl(); // the test will return the correct localhost URL here
    var methanol = Methanol.create();
    var multipartBody = MultipartBodyPublisher.newBuilder()
            .textPart("name", name)
            .formPart("file", HttpRequest.BodyPublishers.ofByteArray(content))
            .build();

    var request = MutableRequest.POST(url, multipartBody);
    methanol.send(request, HttpResponse.BodyHandlers.ofString());
}

我可以在標准輸出中看到完全相同的警告:

2021-06-01 07:22:35.086  WARN 23840 --- [o-auto-1-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'name' is not present]
400

最后,我的application.yaml中有這個:

spring:
  servlet:
    multipart:
      max-file-size: 750MB
      max-request-size: 750MB

server:
  tomcat:
    max-swallow-size: 786432000
    max-http-form-post-size: 786432000

logging:
  level:
    org:
      springframework:
        web:
          filter:
            CommonsRequestLoggingFilter: DEBUG

我設法解決了這個問題。 VideoServiceStub中, name參數必須是String而不是MultipartFile

@PostMapping(value ="/videoservice/videos", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<String> upload(@RequestPart("name") String name, @RequestPart("file") MultipartFile file) {
    return ResponseEntity.status(HttpStatus.OK).body("it works");
}

此外,在sendToVideoServiceUsingJava11中,如果沒有filename ,它就無法工作:

.formPart("file", "filename.mp4", HttpRequest.BodyPublishers.ofByteArray(content))

我從來沒有讓 Spring REST 模板示例工作。 這樣做時無法傳遞文件名: body.add("file", new ByteArrayResource(content)) 也許有人有想法?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM