使用RestTemplate 调用远程接口上传文件方式

 更新时间:2021年09月25日 16:04:28   作者:y_bccl27  
这篇文章主要介绍了使用RestTemplate 调用远程接口上传文件方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

RestTemplate 调用远程接口上传文件

问题描述

第三方写了一个文件上传的接口,该接口的请求方式为Post请求,请求参数全部是以form-data表单形式进行提交,包含三个参数

  • 第一个:cookie(字符串类型)
  • 第二个:seqNo(字符串类型)
  • 第三个:file(文件类型)

解决方法

使用传统的Spring Cloud的Feign组件在调用远程接口实现文件上传时有时会出现异常错误,可考虑使用下述两种方式文件上传

第一种方式

使用RestTemplate进行调用

import org.springframework.core.io.InputStreamResource; 
import java.io.InputStream; 
public class CommonInputStreamResource extends InputStreamResource {
    private long length;
    private String fileName; 
    public CommonInputStreamResource(InputStream inputStream, long length, String fileName) {
        super(inputStream);
        this.length = length;
        this.fileName = fileName;
    }
 
    /**
     * 覆写父类方法
     * 如果不重写这个方法,并且文件有一定大小,那么服务端会出现异常
     * {@code The multi-part request contained parameter data (excluding uploaded files) that exceeded}
     */
    @Override
    public String getFilename() {
        return fileName;
    }
 
    /**
     * 覆写父类 contentLength 方法
     * 因为 {@link org.springframework.core.io.AbstractResource#contentLength()}方法会重新读取一遍文件,
     * 而上传文件时,restTemplate 会通过这个方法获取大小。然后当真正需要读取内容的时候,发现已经读完,会报如下错误。
     */
    @Override
    public long contentLength() {
        long estimate = length;
        return estimate == 0 ? 1 : estimate;
    }
 
    public void setLength(long length) {
        this.length = length;
    }
 
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
}
try{
    String applySeqNo = "123456";
    String cookie="654321";
    File file=new File("E:\\1.rar");
    FileInputStream fileInputStream=new FileInputStream(file);
 
    //请求头设置为MediaType.MULTIPART_FORM_DATA类型
    HttpHeaders requestHeaders = new HttpHeaders();
    requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
    
    //构建请求体
    MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
    CommonInputStreamResource commonInputStreamResource = null;
    try {
        commonInputStreamResource = new CommonInputStreamResource(fileInputStream,file.length(),file.getName());
    } catch (Exception e) { 
        log.error("文件输入流转换错误",e);
    }
    requestBody.add("cookie", cookie);
    requestBody.add("seqNoFile", applySeqNo);
    requestBody.add("file",commonInputStreamResource);
    HttpEntity<MultiValueMap> requestEntity = new HttpEntity<MultiValueMap>(requestBody, requestHeaders);
    
    //直接调用远程接口
    ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://xxx.xxx.xxx.xxx:8080/test/upload",requestEntity, String.class);
    System.out.println("返回结果:"+responseEntity.getBody())
}catch (Exception e){
    log.error("远程调用出现异常:", e);
}

第二种方式

Spring Cloud Feign组件 + MultiValueMap + CommonInputStreamResource

CommonInputStreamResource对象的构造在上面已经实现了这里就不再重复构造,沿用上面的那个就行

feign接口

@Component
@FeignClient(name = "taxRecodes", url = "${spider.url}", qualifier = "TaxRecodeFeignClient",fallback = TaxRecodeFallBack.class)
public interface TaxRecodeFeignClient {    
    /**
     * 单证申请-合同信息表附件上传
     */
    @PostMapping(value = "/attachFile/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    String attachFileUpload(MultiValueMap<String, Object> multiValueMap);
}

请求部分

@PostMapping("/upload")
public void upload(){
    try {
        File file=new File("E:\\1.rar");
        FileInputStream fileInputStream=new FileInputStream(file); 
        CommonInputStreamResource commonInputStreamResource = null;
        try {
            commonInputStreamResource = new CommonInputStreamResource(fileInputStream,fileInputStream.available(),file.getName());
        } catch (Exception e) {
            log.error("文件输入流转换错误:",e);
        } 
        MultiValueMap<String, Object> dto=new LinkedMultiValueMap<String, Object>();
        dto.add("cookie","xxx");
        dto.add("file",commonInputStreamResource);
        dto.add("seqNoFile","xxx");
 
        String returnInfo = taxRecodeFeignClient.attachFileUpload(dto);
        JSONObject returnInfoJsonObject = JSONObject.parseObject(returnInfo);
    }catch (Exception e){
        log.error("异常:",e);
    }
}

RestTemplate调用远程接口添加请求头

项目中我们经常会碰到与第三方系统对接,通过调用第三方系统中的接口来集成服务,为了接口的安全性都为加一些验证,比如:

basic、authority等,通过请求头添加authrization的机制比较容易接入,从第三方系统获取到authorization,然后请求接口时在请求头上带上获取到的authorization,说了怎么多不如直接上代码更容易理解。

// 获取第三方的authorization
String auth= OAuthContentHelper.getAuthorizationHeader();
HttpHeaders requestHeader=new HttpHeaders();
// 将获取到的authorization添加到请求头
requestHeader.add(AuthConstants.AUTHORIZATION_HEADER,auth);
// 构建请求实体
HttpEntity<Object> requestEntity=new HttpEntity(requestParam,requestHeaders);
// 使用restTemplate调用第三方接口
restTemplate.exchage(url,HttpMethod.POST,requestEntity,responseClass);

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot静态资源及原理解析

    SpringBoot静态资源及原理解析

    这篇文章主要介绍了SpringBoot静态资源及原理解析,当创建一个jar工程时,想引入css等静态资源时,需要遵守SpringBoot的静态资源映射关系,通过WebMvcAutoConfiguration查看静态配置资源的规则,需要的朋友可以参考下
    2023-12-12
  • Java中抽象类的作用及说明

    Java中抽象类的作用及说明

    这篇文章主要介绍了Java中抽象类的作用及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 自定义JmsListenerContainerFactory时,containerFactory字段解读

    自定义JmsListenerContainerFactory时,containerFactory字段解读

    这篇文章主要介绍了自定义JmsListenerContainerFactory时,containerFactory字段解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • springboot 启动如何修改application.properties的参数

    springboot 启动如何修改application.properties的参数

    这篇文章主要介绍了springboot 启动如何修改application.properties的参数方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • SpringBoot中的Profile多环境配置方法

    SpringBoot中的Profile多环境配置方法

    这篇文章主要介绍了SpringBoot中的Profile多环境配置,SpringBoot提供了两种多环境配置的方式,分别是使用profile文件进行多环境配置以及使用@Profile注解进行多环境配置,需要的朋友可以参考下
    2023-01-01
  • 一次java异步任务的实战记录

    一次java异步任务的实战记录

    最近做项目的时候遇到了一个小问题,从前台提交到服务端A,A调用服务端B处理超时,下面这篇文章主要给大家介绍了一次java异步任务的实战记录,需要的朋友可以参考下
    2022-05-05
  • 基于SpringMVC拦截器实现接口耗时监控功能

    基于SpringMVC拦截器实现接口耗时监控功能

    本文呢主要介绍了基于SpringMVC拦截器实现的接口耗时监控功能,统计接口的耗时情况属于一个可以复用的功能点,因此这里直接使用 SpringMVC的HandlerInterceptor拦截器来实现,需要的朋友可以参考下
    2024-02-02
  • Java网络编程之基于TCP协议

    Java网络编程之基于TCP协议

    本文主要将Java基于TCP的网络编程主要分解成5个功能:功能分解1:单向通信功能分解,2:双向通信功能分解,3:对象流传送功能分解,4:加入完整的处理异常方式功能分解,5:多线程接收用户请求,需要的朋友可以参考下
    2021-05-05
  • Java中Spring MVC接收表单数据的常用方法

    Java中Spring MVC接收表单数据的常用方法

    Spring MVC是Spring框架中的一个模块,用于开发基于MVC(Model-View-Controller)架构的Web应用程序,它提供了一种轻量级的、灵活的方式来构建Web应用,同时提供了丰富的功能和特性,本文给大家介绍了Spring MVC接收表单数据的方法,需要的朋友可以参考下
    2024-05-05
  • Java设计模式中的组合模式

    Java设计模式中的组合模式

    这篇文章主要介绍了Java设计模式中的组合模式,组合模式依据树形结构来组合对象,用来表示部分以及整体层次,种类型的设计模式属于结构型模式
    2022-07-07

最新评论