好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

查看更多关于使用RestTemplate 调用远程接口上传文件方式的详细内容...

  阅读:14次