閫氳繃`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锛岄偅涔堟垜浠潵鐪嬩竴涓嬪畠鐨勫疄鐜扮被鏈夊摢浜涳細
鎶€鏈浘鐗? src=
浠ヤ笂鏄?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>

  1. 鏄敱浜?鐨勫師鍥狅紝鎵嶉渶瑕?鐨勫瓨鍦?/strong>锛屼笉杩囦娇鐢ㄦ柟寮忔槸瀵圭殑锛?strong>浣跨敤InputStreamResource闇€瑕佽鍐欎袱涓柟娉?code>contentLength鍜?code>getFileName銆?/li>

以上是关于閫氳繃`RestTemplate`涓婁紶鏂囦欢(InputStreamResource璇﹁В)的主要内容,如果未能解决你的问题,请参考以下文章

Jquery.form寮傛涓婁紶鏂囦欢甯歌闂瑙e喅

閫夋嫨鏂囦欢杩涜涓婁紶

python鎺ュ彛鑷姩鍖?-post鏂囦欢涓婁紶

鍒涘缓鏂囦欢涓婁紶琛ㄥ崟

闆嗚绗叚澶╋細鏂囦欢涓婁紶婕忔礊

閰嶇疆php.ini 淇敼php鏂囦欢涓婁紶澶у皬