使用 FeignClient 为 MultipartFile 接收器 API 上传 MultiValueMap 时出现问题

问题描述

我在将 multipartfile 从一项服务发送到另一项服务时遇到问题。

我想调用的 API 是,

@PostMapping(value = "/posts/{postId}/comments/{commentId}/attachments")
@JsonView(CaseJsonView.ClientWithComments.class)
public ResponseEntity<?> createCommentAttachment(@PathVariable final String postId,@PathVariable final String commentId,@RequestParam("payload") final multipartfile multipartfile,@RequestParam final String filename,final HttpServletRequest request) throws JsonProcessingException {
        try {
            FileUtils.writeByteArrayToFile(new File("C:\\CODE\\data\\" + filename),multipartfile.getBytes());
        } catch (IOException e) {
            e.@R_404_1612@();
        }
}

当我像下面这样调用这个 API 时,这里会创建空文件

FeignClient

@FeignClient(name = "post-service")
public interface CommentClient {
    @RequestMapping(method = RequestMethod.POST,value = "/posts/{postId}/comments/{id}/attachments?filename={filename}",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    void storeCommentAttachmentPayload(@PathVariable("postId") String postId,@PathVariable("id") String id,@RequestBody MultiValueMap<String,Object> map,@PathVariable("filename") String filename);
}

我正在使用这个 FeignClient,如下所示,

public void sendAttachment() {
   //Adding only attachment code.
   // Here attachmentClient is some other FeignClient which is returning attachment.
   final Resource resource = attachmentClient.getAttachmentPayloadById(attachementId);
                final multipartfile multipartfile = new InMemorymultipartfile(filename,filename,mimeType,IoUtils.toByteArray(resource.getInputStream()));
                final MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
                final ByteArrayResource byteArrayResource = new 
   ByteArrayResource(multipartfile.getBytes()) {
                    @Override
                    public String getFilename() {
                        return filename == null ? "" : filename;
                    }
                };
   map.add(PAYLOAD,byteArrayResource);
   commentService.storeCommentAttachmentPayload(postId commentId,map,filename);
}

观察: 我的观察是,当我通过这种方法文件保存在磁盘上时,所有数据都会正确显示。 但在接收端保存的是空文件

一个观察结果是接收端的字节数组大小比发送端小。检查下图,

https://i.stack.imgur.com/JjxEZ.png

一个观察结果是文本文件上传正确。

解决方法

所以我终于找到了解决我的问题的方法。我没有使用 FeignClient 上传文件,而是使用 RestTemplate 上传,如下所示,

final List<ServiceInstance> postServiceInstances = discoveryClient.getInstances("post-service");
                if (postServiceInstances != null && !postServiceInstances.isEmpty()) {
                    final HttpEntity<MultiValueMap<String,Object>> entity = new HttpEntity<MultiValueMap<String,Object>>(multiValuMap);
                    final ResponseEntity<String> response = restTemplate
                            .postForEntity(postServiceInstances.get(0).getUri() + "/posts/" + postId + "/comments/" + commentId + "/attachments?filename=" + filename,entity,String.class);
                    if (response.getStatusCode() != HttpStatus.CREATED) {
                        throw new Exception("Exception from post-service: " + response.getStatusCode());
                    }
                } else {
                    throw new Exception("No post-service instance found");
                }

实际上不是一个完美的解决方案,但它解决了我的目的。 此外,我添加了 RestTemplate Interceptor,它在我的请求中添加了一个令牌。

不过,使用 FeignClient 的解决方案将不胜感激。