如何使用RestTemplate调用远程接口上传文件 - 开发技术

博主:xiaoweixiaowei 2023-01-18 条评论

今天就跟大家聊聊有关如何使用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:\.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接口

    如何使用RestTemplate调用远程接口上传文件 - 开发技术
    @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:\.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);

    看完上述内容,你们对如何使用RestTemplate调用远程接口上传文件有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注云行业资讯频道,感谢大家的支持。

    The End

    发布于:2023-01-18,除非注明,否则均为 主机评测原创文章,转载请注明出处。