閫氳繃`RestTemplate`涓婁紶鏂囦欢(InputStreamResource璇﹁В)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了閫氳繃`RestTemplate`涓婁紶鏂囦欢(InputStreamResource璇﹁В)相关的知识,希望对你有一定的参考价值。
鏍囩锛?a href='http://www.mamicode.com/so/1/standard' title='standard'>standard desc tin 璇诲啓 instance his 杩欎竴 catch vat
閫氳繃RestTemplate
涓婁紶鏂囦欢
1.涓婁紶鏂囦欢File
纰板埌涓€涓渶姹傦紝鍦ㄤ唬鐮佷腑閫氳繃HTTP鏂瑰紡鍋氫竴涓獙璇佺殑璇锋眰锛岃姹傜殑鍙傛暟鍖呭惈浜嗘枃浠剁被鍨嬨€傛兂鎯冲叾瀹炲緢绠€鍗曪紝鐩存帴浣跨敤瀹氫箟濂界殑MultiValueMap
锛屾妸鏂囦欢鍙傛暟浼犲叆鍗冲彲銆?/p>
鎴戜滑鐭ラ亾锛宺estTemplate 榛樿瀹氫箟浜嗗嚑涓€氱敤鐨勬秷鎭浆鎹㈠櫒锛岃org.springframework.web.client.RestTemplate#RestTemplate()
锛岄偅涔堟枃浠跺簲璇ュ搴斿摢绉嶈祫婧愬憿锛?/p>
鐪嬩簡涓婇潰杩欎釜鏂规硶涔嬪悗锛屽彲浠ュ緢蹇仈鎯冲埌鏄?code>ResourceHttpMessageConverter锛屼粠绫荤鍚嶄篃鍙互鐪嬪嚭鏉ワ細
Implementation of @link HttpMessageConverter that can read/write @link Resource Resources
and supports byte range requests.
杩欎釜杞崲鍣ㄤ富瑕佹槸鐢ㄦ潵璇诲啓鍚勭绫诲瀷鐨勫瓧鑺傝姹傜殑銆?/p>
鏃㈢劧鏄?code>Resource锛岄偅涔堟垜浠潵鐪嬩竴涓嬪畠鐨勫疄鐜扮被鏈夊摢浜涳細
浠ヤ笂鏄?code>AbstractResource鐨勫疄鐜扮被锛屾湁鍚勭鍚勬牱鐨勫疄鐜扮被锛屼粠鍚嶇О涓婃潵璇村簲璇ユ瘮杈冩湁鐢ㄧ殑搴旇鏄細InputStreamResource
鍜?code>FileSystemResource锛岃繕鏈?code>ByteArrayResource 鍜?UrlResource
绛夈€?/p>
1.1 浣跨敤FileSystemResource
涓婁紶鏂囦欢
杩欑鏂瑰紡浣跨敤璧锋潵姣旇緝绠€鍗曪紝鐩存帴鎶婃枃浠惰浆鎹㈡垚瀵瑰簲鐨勫舰寮忓嵆鍙€?/p>
MultiValueMap<String, Object> resultMap = new LinkedMultiValueMap<>();
Resource resource = new FileSystemResource(file);
param.put("file", resource);
缃戜笂浣跨敤RestTemplate
涓婁紶鏂囦欢澶у鏁版槸杩欑鏂瑰紡锛岀畝鍗曪紝鏂逛究锛屼笉鐢ㄥ仛杩囧鐨勮浆鎹紝鐩存帴浼犻€掑弬鏁板嵆鍙€?/p>
浣嗘槸涓轰粈涔堜細鍐欒繖绡囧崥瀹㈡潵璁板綍鍛紵鍥犱负锛屾湁涓€涓笉鍠滄鐨勫湴鏂瑰氨鏄紝瀹冮渶瑕佷紶閫掍竴涓枃浠躲€傝€屾垜寰楀埌鏄枃浠舵簮鏄竴涓祦锛屾垜闇€瑕佸湪鏈湴鍒涘缓涓€涓复鏃舵枃浠讹紝鐒跺悗鎶?code>InputStream鍐欏叆鍒版枃浠朵腑鍘汇€備娇鐢ㄥ畬涔嬪悗锛岃繕闇€瑕佹妸鏂囦欢鍒犻櫎銆?/p>
閭d箞鏃㈢劧杩欎箞楹荤儲锛屾湁娌℃湁鏇村ソ鐨勬柟寮忓憿锛?/p>
1.2 浣跨敤InputStreamResource
涓婁紶鏂囦欢
杩欎釜绫荤殑鏋勯€犲嚱鏁板彲浠ョ洿鎺ヤ紶鍏ユ祦鏂囦欢銆傞偅涔堝氨鐩存帴璇曡瘯鍚э紒
MultiValueMap<String, Object> resultMap = new LinkedMultiValueMap<>();
Resource resource = new InputStreamResource(inputStream);
param.put("file", resource);
娌℃湁鎯冲埌锛屾湇鍔$鎶ラ敊浜嗭紝杩斿洖鐨勬槸锛氭病鏈変紶閫掓枃浠躲€傝繖鍙氨绾抽椃浜嗭紝鏄庢槑宸茬粡鏈変簡鍟娿€?/p>
缃戜笂浣跨敤杩欑鏂瑰紡涓婁紶鐨勬柟寮忎笉澶氾紝鍙壘鍒拌繖涔堜竴涓枃浠讹紝浣嗗凡缁忓浜嗭細RestTemplate閫氳繃InputStreamResource涓婁紶鏂囦欢.
鍗氫富鐨勭枒闂拰鎴戜竴鏍凤紝涓嶆兂鍘诲垱寤烘湰鍦版枃浠讹紝鐒跺悗灏变娇鐢ㄤ簡杩欎釜娴佺殑鏂瑰紡銆備絾鏄篃纰板埌浜嗛棶棰樸€?/p>
鏂囩珷鍐欏緱寰堟竻鏅帮細浣跨敤InputStreamResource
涓婁紶鏂囦欢鏃讹紝闇€瑕侀噸鍐欒绫荤殑涓や釜鏂规硶锛?code>contentLength鍜?code>getFilename銆?/p>
鏋滅劧鎸夌収杩欎釜鏂囩珷鐨勬€濊矾灏濊瘯涔嬪悗锛屽氨鎴愬姛浜嗐€備唬鐮佸涓嬶細
public class CommonInputStreamResource extends InputStreamResource
private int length;
public CommonInputStreamResource(InputStream inputStream)
super(inputStream);
public CommonInputStreamResource(InputStream inputStream, int length)
super(inputStream);
this.length = length;
/**
* 瑕嗗啓鐖剁被鏂规硶
* 濡傛灉涓嶉噸鍐欒繖涓柟娉曪紝骞朵笖鏂囦欢鏈変竴瀹氬ぇ灏忥紝閭d箞鏈嶅姟绔細鍑虹幇寮傚父
* @code The multi-part request contained parameter data (excluding uploaded files) that exceeded
*
* @return
*/
@Override
public String getFilename()
return "temp";
/**
* 瑕嗗啓鐖剁被 contentLength 鏂规硶
* 鍥犱负 @link org.springframework.core.io.AbstractResource#contentLength()鏂规硶浼氶噸鏂拌鍙栦竴閬嶆枃浠讹紝
* 鑰屼笂浼犳枃浠舵椂锛宺estTemplate 浼氶€氳繃杩欎釜鏂规硶鑾峰彇澶у皬銆傜劧鍚庡綋鐪熸闇€瑕佽鍙栧唴瀹圭殑鏃跺€欙紝鍙戠幇宸茬粡璇诲畬锛屼細鎶ュ涓嬮敊璇€? * <code>
* java.lang.IllegalStateException: InputStream has already been read - do not use InputStreamResource if a stream needs to be read multiple times
* at org.springframework.core.io.InputStreamResource.getInputStream(InputStreamResource.java:96)
* </code>
* <p>
* ref:com.amazonaws.services.s3.model.S3ObjectInputStream#available()
*
* @return
*/
@Override
public long contentLength()
int estimate = length;
return estimate == 0 ? 1 : estimate;
鍏充簬contentLength
鏂囩珷閲岃鐨勫緢娓呮锛氫笂浼犳枃浠舵椂resttemplate浼氶€氳繃杩欎釜鏂规硶寰楀埌inputstream鐨勫ぇ灏忋€?/p>
鑰?code>InputStreamResource鐨?code>contentLength鏂规硶鏄户鎵?code>AbstractResource锛屽畠鐨勫疄鐜板涓嬶細
InputStream is = getInputStream();
Assert.state(is != null, "Resource InputStream must not be null");
try
long size = 0;
byte[] buf = new byte[255];
int read;
while ((read = is.read(buf)) != -1)
size += read;
return size;
finally
try
is.close();
catch (IOException ex)
宸茬粡璇诲畬浜嗘祦锛屽鑷翠細鎶ラ敊锛屽叾瀹?code>InputStreamResource鐨勭被绛惧悕鏄凡缁忔敞鏄庝簡锛氬鏋滈渶瑕佹妸娴佽澶氭锛屼笉瑕佷娇鐢ㄥ畠銆?/p>
Do not use an @code InputStreamResource if you need to
keep the resource descriptor somewhere, or if you need to read from a stream
multiple times.
鎵€浠ラ渶瑕佸儚鎴戜笂闈竴鏍锋敼鍐欎竴涓嬶紝鐒跺悗灏卞彲浠ュ畬鎴愪簡銆傞偅涔堝師鐞嗗埌搴曟槸涓嶆槸杩欐牱鍛紵缁х画鐪嬨€?/p>
2. RestTemplate
涓婁紶鏂囦欢鏃剁殑澶勭悊
涓婇潰鎴戜滑璇村埌RestTemplate
鍒濆鍖栨椂锛岄渶瑕佹敞鍐屽嚑涓秷鎭浆鎹㈠櫒锛岄偅涔堝叾涓湁涓€涓氨鏄?code>ResourceHTTPMessageConverter锛岄偅涔堟垜浠湅鐪嬪畠瀹屾垚浜嗗摢浜涘姛鑳藉憿锛?br />
鏂规硶寰堝皯锛屼竴涓嬪瓙灏卞彲浠ョ湅瀹岋細鍏充簬鏂囦欢澶у皬锛坈ontentLength锛夛紝鏂囦欢绫诲瀷锛圕ontentType锛夛紝璇伙紙readInternal锛夛紝鍐欙紙org.springframework.http.converter.ResourceHttpMessageConverter#writeInternal锛夌瓑鏂规硶銆?/p>
涓婇潰鐨勭浜岀偣锛屾垜浠InputStreamResource
涓嶅仛浠讳綍澶勭悊鏃讹紝浼氬鑷存枃浠跺娆¤鍙栵紝閭d箞鏄€庝箞鍋氱殑鍛紝鎴戜滑鐪嬬湅婧愮爜锛?/p>
3. 鏈嶅姟绔笂浼犳枃浠舵椂鐨勫鐞?/h2>
鏂囦欢婧?br /> AbstractMultipartHttpServletRequest # multipartFiles
璧嬪€?br />
StandardMultipartHttpServletRequest # parseRequest
闇€瑕?disposition 锛?quot;content-disposition"锛夐噷鏈夆€渇ilename=鈥?瀛楁鎴栬€呪€渇ilename*=鈥濓紝浠庨噷闈㈣幏鍙?fileName
io.undertow.servlet.spec.HttpServletRequestImpl#loadParts 閲屽 getParts 璧嬪€?/p>
MultiPartParserDefinition #io.undertow.servlet.spec.HttpServletRequestImpl#loadParts 瑙f瀽 琛ㄥ崟鏁版嵁
- 鍏朵腑鑾峰彇娴?ServletInputStreamImpl
鎸夌収涓婇潰鐨勬祦绋嬫帓鏌ヤ笅鏉ワ紝娌℃湁鍙戠幇鏈変粈涔堥棶棰橈紝鍞竴鍑洪棶棰樼殑鍦版柟鏄姹備腑鐨勨€渄iposition鈥濆瓧娈佃缃湁闂锛屾病鏈夋妸filename=
鏀惧叆锛屽鑷磋В鏋愪笉鍒版枃浠躲€?/p>
3.1 閲嶆柊鍥炲埌璇锋眰浣撳啓鍏?code>FormHttpMessageConverter#writePart
浠庤繖涓柟娉曚腑锛屾垜浠彲浠ョ湅鍒板悇涓浆鎹㈠櫒鐨勯亶鍘嗚皟鐢ㄣ€傜湅鐪嬩笅闈㈢殑浠g爜锛?/p>
private void writePart(String name, HttpEntity<?> partEntity, OutputStream os) throws IOException
Object partBody = partEntity.getBody();
Class<?> partType = partBody.getClass();
HttpHeaders partHeaders = partEntity.getHeaders();
MediaType partContentType = partHeaders.getContentType();
for (HttpMessageConverter<?> messageConverter : this.partConverters)
if (messageConverter.canWrite(partType, partContentType))
HttpOutputMessage multipartMessage = new MultipartHttpOutputMessage(os);
multipartMessage.getHeaders().setContentDispositionFormData(name, getFilename(partBody)); // 1
if (!partHeaders.isEmpty())
multipartMessage.getHeaders().putAll(partHeaders);
((HttpMessageConverter<Object>) messageConverter).write(partBody, partContentType, multipartMessage);
return;
throw new HttpMessageNotWritableException("Could not write request: no suitable HttpMessageConverter " +
"found for request type [" + partType.getName() + "]");
浠庝腑鎴戜滑鍙互鐪?code>setContentDispositionFormData杩欎竴琛岋細getFileName
鏂规硶锛岃繖閲屼細璧板埌鍚勪釜Resource
鐨?code>getFileName鏂规硶銆?/p>
鐪熺浉鍗冲皢寰楀埌锛?code>InputStreamResource 鐨勮繖涓柟娉曟槸缁ф壙鑷?code>org.springframework.core.io.AbstractResource#getFilename锛岃繖涓柟娉曠洿鎺ヨ繑鍥瀗ull銆備箣鍚庣殑灏卞緢绠€鍗曚簡锛氬綋fileName涓簄ull鏃讹紝涓嶄細鍦?code>setContentDispositionFormData涓妸filename=
鎷煎叆銆傛墍浠ユ湇鍔$涓嶄細瑙f瀽鍒版枃浠讹紝瀵艰嚧鎶ラ敊銆?/strong>
4. 缁撹
1銆佷娇鐢?code>RestTemplate涓婁紶鏂囦欢浣跨敤FileSystemResource
鍦ㄧ洿鎺ユ槸鏂囦欢鐨勬儏鍐典笅寰堢畝鍗曘€?br />
2銆佸鏋滀笉鎯冲湪鏈湴鏂板缓涓存椂鏂囦欢鍙互浣跨敤锛?code>InputStreamResource锛屼絾鏄渶瑕佽鍐?code>FileName鏂规硶銆?br />
3銆佺敱浜?鐨勫師鍥狅紝2.2.1 涓殑contentLength
鏂规硶锛屼笉浼氬InputStreamResource
鍋氱壒娈婂鐞嗭紝鑰屾槸鐩存帴鍘昏鍙栨祦锛屽鑷存祦琚鍙栧娆★紱鎸夌収绫荤鍚嶏紝浼氭姤閿欍€傛墍浠ヤ篃闇€瑕佽鍐?code>contentLength鏂规硶銆?/p>
- 鏄敱浜?鐨勫師鍥狅紝鎵嶉渶瑕?鐨勫瓨鍦?/strong>锛屼笉杩囦娇鐢ㄦ柟寮忔槸瀵圭殑锛?strong>浣跨敤InputStreamResource闇€瑕佽鍐欎袱涓柟娉?code>contentLength鍜?code>getFileName銆?/li>
以上是关于閫氳繃`RestTemplate`涓婁紶鏂囦欢(InputStreamResource璇﹁В)的主要内容,如果未能解决你的问题,请参考以下文章