RestTemplate 调用远程接口上传文件
问题描述
第三方写了一个文件上传的接口,该接口的请求方式为Post请求,请求参数全部是以form-data表单形式进行提交,包含三个参数
- 第一个:cookie(字符串类型)
- 第二个:seqNo(字符串类型)
- 第三个:file(文件类型)
解决方法
使用传统的Spring Cloud的Feign组件在调用远程接口实现文件上传时有时会出现异常错误,可考虑使用下述两种方式文件上传
第一种方式
使用RestTemplate进行调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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接口
1
2
3
4
5
6
7
8
9
|
@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);
}
|
请求部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@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,说了怎么多不如直接上代码更容易理解。
1
2
3
4
5
6
7
8
9
|
// 获取第三方的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);
|
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/y_bccl27/article/details/115088532