SpringBoot创建RestTemplate下载图片时url被转义的问题解决

  

问题:

  

在实际项目中,对传入的图片网址进行下载,使用的是创建RestTemplate的交换方法,具体如下:

  

使用以下创建RestTemplate的方法:

  
 <代码> sr url=" http://10.64.203.183:6120/图片吗?=d6ei2a4i9c84 * 33 c - 793=11 i5m * ep5t9d5=1 * 2 pdi=* s5i2=94 b8i5d2e * 14 b863328-aa2e959-1b246b-43s=10 d3z83”;
  ResponseEntity 
  

用这种方式调用请求,抓拍可看出url中的特殊字符被转义:

  
 <代码> http://10.64.203.183:6120图片? d6ei2a4i9c84 * 33 c - 793=11 i5m * ep5t9d5 % 3 d * 2 pdi % 3 d * 1 s5i2 % 3 d94b8i5d2e * 14 b863328-aa2e959-1b246b-43s % 3 d10d3z83  
  

由于第三方的图片服务器,没有对请求的url进行解码,因此不识别转义后的url导致下载失败。

  

解决方法:

  

如果不希望被转码,则可使用
公共& lt; T>ResponseEntity交换(URI url, HttpMethod方法,@Nullable HttpEntity<?比;requestEntity ClassresponseType)
该方法,直接传入URI对象。
该对象可如下进行组装:

  
 <代码> sr url=" http://10.64.203.183:6120/图片吗?=d6ei2a4i9c84 * 33 c - 793=11 i5m * ep5t9d5=1 * 2 pdi=* s5i2=94 b8i5d2e * 14 b863328-aa2e959-1b246b-43s=10 d3z83”;
  URI URI=新的URI (url);
  创建restTemplate。交易所(url, HttpMethod。零,byte [] . class);  
  

这样,网址就不会被编码成utf - 8,不会将特殊字符转义,解决了下载失败的问题。

  

源码分析

  

以下是url被转码的源码分析。

  

对应的包为

  
 <代码> sr url=" http://10.64.203.183:6120/图片吗?=d6ei2a4i9c84 * 33 c - 793=11 i5m * ep5t9d5=1 * 2 pdi=* s5i2=94 b8i5d2e * 14 b863328-aa2e959-1b246b-43s=10 d3z83”;
  ResponseEntity 
  

对应源码的调用关系:

  
 <代码> RestTemplate.class:
  
  公共& lt; T>ResponseEntity交换(字符串url, HttpMethod方法,@Nullable HttpEntity<?比;requestEntity ClassresponseType Map<字符串,比;uriVariables)抛出RestClientException {
  RequestCallback RequestCallback=ttpEntityCallback (requestEntity responseType);
  ResponseExtractor比;responseExtractor=this.responseEntityExtractor (responseType);
  返回null (ResponseEntity)(这一点。执行(url,方法,用于,responseExtractor uriVariables));
  }
   
  
 <代码> RestTemplate.class:
  
  @Nullable
  公共& lt; T>T(字符串url, HttpMethod执行方法,@Nullable RequestCallback RequestCallback, @Nullable ResponseExtractorresponseExtractor Map<字符串,比;uriVariables)抛出RestClientException {
  URI=this.getUriTemplateHandler扩大()。扩大(url, uriVariables);
  返回。doExecute(扩大,方法,用于responseExtractor);
  }
   
  

从执行函数可看的出,源码中会将url字符串对象转成URI对象。

  

转换的源码如下:

  
 <代码> DefaultUriBuilderFactory.class:
  
  扩大公共URI(字符串uriTemplate Map<字符串,?比;uriVars) {
  返回this.uriString (uriTemplate) .build (uriVars);
  }
   
  

我们来看下this.uriString (uriTemplate),返回的是UriBuilder对象,

  
 <代码>
  公共UriBuilder uriString(字符串uriTemplate) {
  返回新DefaultUriBuilderFactory.DefaultUriBuilder (uriTemplate);
  }
   
  
 <代码>
  私人类DefaultUriBuilder实现UriBuilder:
  
  公共DefaultUriBuilder(字符串uriTemplate) {
  这一点。uriComponentsBuilder=this.initUriComponentsBuilder (uriTemplate);
  }
  
  私人UriComponentsBuilder initUriComponentsBuilder(字符串uriTemplate) {
  UriComponentsBuilder结果;
  如果(! StringUtils.hasLength (uriTemplate)) {
  结果=DefaultUriBuilderFactory.this。baseUri !=零?DefaultUriBuilderFactory.this.baseUri.cloneBuilder (): UriComponentsBuilder.newInstance ();
  如果(DefaultUriBuilderFactory.this}其他。baseUri !=null) {
  UriComponentsBuilder builder=UriComponentsBuilder.fromUriString (uriTemplate);
  UriComponents uri=builder.build ();
  结果=uri.getHost()==零?DefaultUriBuilderFactory.this.baseUri.cloneBuilder () .uriComponents (uri):施工;
  其他}{
  结果=UriComponentsBuilder.fromUriString (uriTemplate);
  }
  
  如果(DefaultUriBuilderFactory.this.encodingMode.equals (DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES)) {
  result.encode ();
  }
  
  this.parsePathIfNecessary(结果);
  返回结果;
  }

SpringBoot创建RestTemplate下载图片时url被转义的问题解决