zuul feign微服务间文件上传

feign传文件

  • 需求
  1. 文件微服务负责管理文件,具体的文件上传下载逻辑都在此模块。
  2. openAPI负责向app用户提供头像上传的接口,实现具体业务逻辑。
  3. zuul是网关,负责路由转发。用户直接访问网关。

头像文件==》zuul==》openAPI==》文件微服务

  • 增加引用包
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form-spring</artifactId>
            <version>2.1.0</version>
        </dependency>
  • 增加配置类
@Configuration
public class FeignConfiguration {
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;
    @Bean
    public Retryer retryer(){
        return new Retryer.Default(1000,10000,3);
    }

    @Bean
    Request.Options feignOptions() {
        return new Request.Options(5 * 1000, 10 * 1000);
    }

    // 主要是这个地方
    @Bean
    @Primary
    @Scope("prototype")
    public Encoder multipartFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    @Bean
    public ErrorDecoder errorDecoder(){
        return new FeignErrorDecoder();
    }

}

异常处理类

public class FeignErrorDecoder implements feign.codec.ErrorDecoder {
    private static final Logger logger = LoggerFactory.getLogger(FeignErrorDecoder.class);

    @Override
    public Exception decode(String methodKey, Response response) {

        if(response.status() >= 400 && response.status() <= 499){
            return new HystrixBadRequestException("微服务之间调用失败!");
        }

        return feign.FeignException.errorStatus(methodKey, response);
    }

}

在启动类上加注解@Import(FeignConfiguration.class),导入配置类

@Import(FeignConfiguration.class)

至此可实现feign中文件传递

feignclient

 @ApiOperation(value = "用户修改头像", notes = "用户修改头像")
 @RequestMapping(value = "/v1/user/avatar", method = RequestMethod.PUT)
 public CommonResponse editAvatar(@RequestHeader(value = "openId") String openId,
                                     @RequestPart(value = "file") MultipartFile avatarFile);
  1. RequestPart中的name要和上传时一致,否则调用失败。
  2. feign中@RequestHeader传递null时,会自动转为{fileLength},需要手动处理。

zuul

微服务上传文件成功后,通过zuul网关上传又出现问题,文件传不到微服务中。

org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present

解决方法:
在调用地址前加上/zuul(/zuul/v1/user/avatar),绕过spring mvc,使用zuul servlet去上传文件。

参考:https://my.oschina.net/kmnztech/blog/1618636

或者在网关的application.properties中设置servlet-path属性

zuul.servlet-path=/

官方文档:

http://cloud.spring.io/spring-cloud-static/Dalston.SR1/#_uploading_files_through_zuul

The Zuul Servlet
Zuul is implemented as a Servlet. For the general cases, Zuul is embedded
into the Spring Dispatch mechanism. This allows Spring MVC to be in control
of the routing. In this case, Zuul is configured to buffer requests. If
there is a need to go through Zuul without buffering requests (e.g. for
large file uploads), the Servlet is also installed outside of the Spring
Dispatcher. By default, this is located at /zuul. This path can be changed
with the zuul.servlet-path property.

猜你喜欢

转载自www.cnblogs.com/iiot/p/9567255.html