问题:
在实际项目中,对传入的图片网址进行下载,使用的是创建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对象。
该对象可如下进行组装:
<代码> 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 Class responseType 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被转义的问题解决