如何在Spring Boot中将Multipart文件从一个服务传递到另一个服务?

4
我希望能够将多部分文件从一个服务传递到另一个服务。
客户端-->服务1-->服务2
当我从Service1传递文件到Service2时,会显示错误“500内部服务器错误,当前请求不是多部分请求”。
当我直接发送文件到Client-->Service2时,它可以工作,但通过Service1却不行。
我想知道可能的原因,我猜测在将多部分文件作为参数传递时,我可能错过了一些头部信息。 服务2
@PostMapping(path="/upload")
public ResponseEntity<Properties> upload(@RequestParam("file") MultipartFile multiPart) {
    return saveFile(multiPart);
}

Service2客户端

@FeignClient
(name="${feign.upload.serverId}", configuration = UploadServiceClientConfiguration.class, decode404 = true)
public interface UploadServiceClient {

    @PostMapping(path="/upload")
    ResponseEntity<Properties> upload(@RequestParam("file") MultipartFile multiPart);

    class UploadServiceClientConfiguration {
        @Value(value="${feign.upload.user}")
        String user;
        @Value(value="${feign.upload.password}")
        String password;
        @Bean
        public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
            return new BasicAuthRequestInterceptor(user, password);
        }
    }
}

服务1

@Autowired
UploadServiceClient uploadSvcClient;
@PostMapping(path="/upload")
public ResponseEntity<Properties> uploadAttachment(@RequestParam("file") MultipartFile file) {
    return uploadSvcClient.upload(file);
}
2个回答

3

最终使用文件上传Spring Cloud Feign客户端成功解决与另一个服务的通信问题。

我已经将FeignClient参数类型从

@RequestParam("file") MultipartFile mFile

改为

@RequestPart("file") MultiValueMap file.

FeignClient签名

@PostMapping(value="/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
        ResponseEntity<Properties> upload(@RequestHeader(name=UID,required=false) String uid, @RequestPart("file") MultiValueMap<String, Object> file);

Service1实现

@PostMapping(path="/upload")
    public ResponseEntity<Properties> uploadAttachment(@RequestHeader(IRSConsts.UID) String uid, @RequestParam("file") MultipartFile mFile) {
        MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        ByteArrayResource contentsAsResource = null;
        try {
            contentsAsResource = new ByteArrayResource(mFile.getBytes()) {
                @Override
                public String getFilename() {
                    return mFile.getOriginalFilename();
                }
            };
        } catch (IOException e) {
            e.printStackTrace();
        }
        multiValueMap.add("file", contentsAsResource);
        return transSvcClient.upload(uid, multiValueMap);
    }

Service2 实现

@PostMapping(path = "/upload")
    @Headers("Content-Type: multipart/form-data")
    public ResponseEntity<Properties> upload(@RequestHeader(name = UID, required = false) String uid,
            @RequestPart("file") MultipartFile multiPart) {
        //Save Attachment.
    }

0

也许您需要一个表明请求是多部分的标头。 这个答案是否解决了您的问题? 所需的是一个标头注释:

@PostMapping(path="/upload")
@Headers("Content-Type: multipart/form-data")
ResponseEntity<Properties> upload(@Param("file") MultipartFile multiPart);

这只是一个假设。请尝试一下并让我知道结果。


我之前尝试过这个,但是出现了以下错误。feign.FeignException: status 400 reading UploadServiceClient #upload(String,MultipartFile); content: {"timestamp":"2020-01-09T19:01:44+0000","status":400,"error":"Bad Request","message":"Required request part 'file' is not present","path":"/upload"} at feign.FeignException.errorStatus(FeignException.java:60) at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:89) at - Gopikrishna Mandapati
啊,我找到了区别,请尝试使用@Param而不是@RequestParam。我已经更新了我的答案。 - Stepan Tsybulski
不,它仍然显示相同的错误。feign.FeignException: status 400 reading UploadServiceClient#upload(String,MultipartFile); content: {"timestamp":"2020-01-09T19:21:20+0000","status":400,"error":"Bad Request","message":"Required request part 'file' is not present","path":"/upload"} - Gopikrishna Mandapati
我认为我正在传递多部分对象本身。我认为我必须将其包装并分配给“文件”参数,但我不知道如何做。如果您知道,请帮助我。 - Gopikrishna Mandapati
我相信你已经做得很正确了。让我们再试一次。阅读这个答案 https://dev59.com/tlwZ5IYBdhLWcg3wLdsF#58770206。它告诉你应该使用 @RequestPart。因为根据响应,你得到的是400,告诉你服务在请求中找不到file部分。 - Stepan Tsybulski
还是遇到同样的错误?好的,我告诉你一个技巧。尝试使用Netcat,然后访问https://www.computerhope.com/unix/nc.htm。您需要运行`nc -lk 9000在端口9000上运行服务器。然后,您可以将请求从服务1传递到服务2,服务2将其转发到localhost:9000`,然后您可以分析请求中确切的内容并找出缺少什么。 - Stepan Tsybulski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接