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