使用Feign上传文件 - multipart/form-data

17

我想使用feign实现多部分文件上传,但似乎找不到好的例子。我希望HTTP请求最终类似于这样:

...
Content-Type: multipart/form-data; boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="name"

Larry
--AaB03x
   Content-Disposition: form-data; name="file"; filename="file1.txt"
   Content-Type: text/plain

... contents of file1.txt ...
--AaB03x--

甚至可以...

------fGsKo01aQ1qXn2C
Content-Disposition: form-data; name="file"; filename="file.doc"
Content-Type: application/octet-stream

... binary data ...

------fGsKo01aQ1qXn2C--

我需要手动构建请求正文,包括生成多部分边界吗?考虑到客户端所能做的一切,这似乎有点过度。

7个回答

10
不用。您只需要定义一种代理接口方法,并将内容类型指定为: multipart/form-data,以及其他远程API所需的参数等信息。以下是一个例子:
public interface FileUploadResource {

    @RequestLine("POST /upload")
    @Headers("Content-Type: multipart/form-data")
    Response uploadFile(@Param("name") String name, @Param("file") File file);

} 

完成的示例可以在这里找到:使用Open Feign上传文件

8

对于Spring Boot 2和spring-cloud-starter-openfeign,请使用以下代码:

@PostMapping(value="/upload", consumes = "multipart/form-data" )
QtiPackageBasicInfo upload(@RequestPart("package") MultipartFile package);

你需要在feign客户端调用中将@RequestParam更改为@RequestPart以使其正常工作,并且还需要在@PostMapping中添加consumes。

3

MBozic 的解决方案不完整,您还需要启用编码器:


public class FeignConfig {
     
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public Encoder feignFormEncoder () {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }
}

@FeignClient(name = "file", url = "http://localhost:8080", configuration = FeignConfig.class)
public interface UploadClient {
    @PostMapping(value = "/upload-file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    String fileUpload(@RequestPart(value = "file") MultipartFile file);
}

3
如果您已经在使用Spring Web,您可以尝试我的Feign编码器实现,它能够创建多部分请求。它可以发送单个文件、一个文件数组以及一个或多个额外的JSON负载。这是我的测试项目。如果您不使用Spring,则可以通过更改FeignSpringFormEncoder中的encodeRequest方法来重构代码。

1
这是一个惊人的实现。我已经苦思冥想了好几天,试图使用FeignClient在单个调用中传递文件和JSON Body,而这个方法完美地解决了这个问题。非常感谢。 - Ajinkya Mahagaonkar

1
你不需要使用自定义头部来构建自定义请求。

@FeignClient("file-service")
public interface FileClient {
    
        @PostMapping(path = "/api/v1/file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
        ResponseEntity<String> save(
                @RequestHeader("userId") Long userId,
                @RequestParam("contentId") UUID contentId,
                @RequestPart("file") MultipartFile file
        );
}

这里我使用了consumes = MediaType.MULTIPART_FORM_DATA_VALUE来选择内容类型,并且注解@RequestPart("file")用于将file标记为多部分文件(如果你使用@RequestParam,它将无法工作)。

很棒的回答。改动较少。 - undefined

0

使用Feign客户端接口从一个服务调用另一个服务进行文件传输/上传/发送:

@FeignClient(name = "service-name", url = "${service.url}", configuration = FeignTokenForwarderConfiguration.class)

public interface UploadFeignClient {

@PostMapping(value = "upload", headers = "Content-Type= multipart/form-data", consumes = "multipart/form-data")
public void upload(@RequestPart MultipartFile file) throws IOException;

}

**Actual API:**

@RestController

@RequestMapping("upload")

public class UploadController {

@PostMapping(value = "/upload", consumes = { "multipart/form-data" })   
public void upload(@RequestParam MultipartFile file) throws IOException {

//implementation

}

}

0

让我为最新的OpenFeign添加答案:

  1. 添加Feign-Form依赖项:

    io.github.openfeign.form feign-form 3.8.0
  2. 像这样向您的Feign.Builder添加FormEncoder:

SomeApi github = Feign.builder() .encoder(new FormEncoder()) .target(SomeApi.class, "http://api.some.org");

  1. API端点

@RequestLine("POST /send_photo") @Headers("Content-Type: multipart/form-data") void sendPhoto (@Param("is_public") Boolean isPublic, @Param("photo") FormData photo);

参考:https://github.com/OpenFeign/feign-form


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