欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-18 23:07:09
目录resttemplate 调用远程接口上传文件resttemplate调用远程接口添加请求头resttemplate 调用远程接口上传文件问题描述第三方写了一个文件上传的接口,该接口的请求方式为p...

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);

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