如何在 Spring 引导分段上传中修复"Required request part is not present"



虽然我的问题与此类似,但我没有使用MockMultipartFile。这是我的用例。

在Spring Boot 2.4.5应用程序中,我编写了一个执行代码的单元测试,它应该发送一个multipart/form-data请求。为了能够从测试中测试接收端,我启动了一个Controller作为multipart/form-data调用的接收器。这是控制器(它当前没有对参数执行任何操作(。

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来中继数据并将其发送到其他地方。单元测试将触发以下代码执行,该代码使用SpringRestTemplate。

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失败,我可以在stdout日志中看到这一点:

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());
}

我可以在stdout中看到完全相同的警告:

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))

我从未使用过SpringREST模板示例。执行以下操作时无法传递文件名:body.add("file", new ByteArrayResource(content))。也许有人有主意?

相关内容

最新更新