Spring Boot 使用OpenFeign 进行上传下载

1. 版本信息

  • SpringBoot与SpringCloud的版本依赖如下(pom.xml)
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
    </parent>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
  • OpenFeign 的版本
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  • OpenFeign-form依赖 (上传下载会用到,如果单纯用OpenFeign请求不需要引入)
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form-spring</artifactId>
            <version>3.4.1</version>
        </dependency>

2. 定义请求的接口文件

  • 上传接口

@FeignClient(
        url = "${api.upload.host}",
        name = "API-Uploader",
        configuration = APIUploader.UploadConfig.class)
@Service
public interface APIUploader {

    @PostMapping(value = "${api.upload.uri}",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    RespData uploadDataFile(@RequestParam Map<String, String> map, @Param(value = "file") MultipartFile file);

    @Slf4j
    class UploadConfig {

        @Autowired
        private ObjectFactory<HttpMessageConverters> messageConverters;
        @Bean
        public Encoder feignFormEncoder () {
            return new SpringFormEncoder(new SpringEncoder(messageConverters));
        }

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

        @Bean
        public Logger feignLogger(){
            return new Logger(){
                @Override
                protected void log(String s, String s1, Object... objects) {
                    log.info(String.format(methodTag(s) + s1, objects));
                }
            };
        }
    }

}

需要注意以下几点:

  1. api.upload.host 与 api.upload.uri 需要在SpringBoot的application.yml文件中配置

  2. 通过修改UploadConfig.feignLoggerLevel 的日志级别来控制显示日志

  3. 上传的文件为MultipartFile,在上传前需要对文件进行转化,转化代码如下

    public static MultipartFile toMultipartFile(String filepath) throws IOException {
        File file = new File(filepath);
        FileItem fileItem = new DiskFileItem("file", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
        byte[] buffer = new byte[4096];
        int n;
        InputStream inputStream = new FileInputStream(file);
        OutputStream os = fileItem.getOutputStream();

        while ( (n = inputStream.read(buffer,0,4096)) != -1){
            os.write(buffer,0,n);
        }
        //注意关闭文件流防止内存泄露
        inputStream.close();
        os.close();
        MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
        return multipartFile;
    }
  • 上传请求
//注入
@AutoWired
APIUploader uploader;
// 省略业务代码
//获取请求参数,细节省略
Map<String,String> requestParams = apiUtil.getRequestParams();
//本地文件路径
String localFile = "/path/to/file"
RespData respData = uploader.uploadDataFile(requestParams, FileUtil.toMultipartFile(localFile));
//判断结果
if (respData.getCode() == apiUtil.API_RESP_CODE_OK) {
    log.info("local file {} upload success,response {}",localFile,respData.getData());
}else {
    log.error("local file {} upload failed,response {}",localFile,respData.getMessage());
}
  • 下载接口
@FeignClient(
        url = "${api.download.host}",
        name = "API-Downloader",
        configuration = APIDownloader.DownloadConfig.class)
@Service
public interface APIDownloader {

    @RequestMapping(value = "/{fileURI}")
    byte[] download(@RequestHeader("Authorization") String authHeader, @PathVariable("fileURI") String fileURI);

    @Slf4j
    class DownloadConfig {

        @Autowired
        private ObjectFactory<HttpMessageConverters> messageConverters;

        @Bean
        public Decoder feignDecoder () {
            List<HttpMessageConverter<?>> springConverters =
                    messageConverters.getObject().getConverters();

            List<HttpMessageConverter<?>> decoderConverters =
                    new ArrayList<HttpMessageConverter<?>>(springConverters.size() + 1);

            decoderConverters.addAll(springConverters);
            decoderConverters.add(new SpringManyMultipartFilesReader(4096));

            HttpMessageConverters httpMessageConverters = new HttpMessageConverters(decoderConverters);

            return new SpringDecoder(new ObjectFactory<HttpMessageConverters>() {

                @Override
                public HttpMessageConverters getObject() {
                    return httpMessageConverters;
                }
            });
        }

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

        @Bean
        public Logger feignLogger(){
            return new Logger(){
                @Override
                protected void log(String s, String s1, Object... objects) {
                    log.info(String.format(methodTag(s) + s1, objects));
                }
            };
        }
    }
}

注意以下事项:

  1. @RequestHeader(“Authorization”) String authHeader 指的是需要http auth认证的头信息内容,如果不需要可以置空
  2. 跟上传一样api.download.host需要在application.yml文件中配置
  3. @PathVariable(“fileURI”) String fileURI 指的是下载文件的URI,下载的完整路径应该${api.download.host} + fileURI
  4. 请求返回的byte[]的字节流,需要写入本地文件,对应的方法如下:
    public static void writeBytesToLocalFile(String localFilePath,byte[] bytes) throws IOException {
        OutputStream outputStream = new FileOutputStream(localFilePath);
        outputStream.write(bytes);
        outputStream.close();
    }
  • 下载请求代码
//注入
@AutoWired
APIDownloader downloader;
// 省略业务代码
// 设置下载文件的URI
String remoteFileURI = "/remotepath/to/file";
// 设置http auth请求的信息
String authHeader = "";
if(enableAuth) {
    authHeader = "Basic " + Encryptor.base64encode(authUser + ":" + authPassword);
}
String localFile = "/path/to/file";
FileUtil.writeBytesToLocalFile(localFile,downloader.download(authHeader,remoteFileURI));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值