一、前言
今天在做数据迁移时,项目旧数据迁移至新数据仓库中,有网络资源下载 重传的需求,于是在整理的过程中,出现了上述问题, java.io.IOException: Server returned HTTP response code: 400 for URL。
当时使用的是 org.apache.commons.io.FileUtils 封装的文件下载包,一个很简单的调用,如下:
try {
String url = "https://XXX.com/audio/15359421531172 He was a boy! ..mp3";
//String url2 = "https://XXX.com/audio/15359421531172 He was a boy.mp3";
String dir = "/tmp/test/";
String fileName = "12.mp3";
URL resourceUrl = new URL(url);
File dirFile = new File(dir);
if (!dirFile.exists()) {
dirFile.mkdirs();
}
FileUtils.copyURLToFile(resourceUrl, new File(dir + fileName));
} catch (Exception e) {
e.printStackTrace();
}
其他的url在下载时候并没有出现上述问题,但在上述的url在下载的时候,爆出了错误400。可以明显的看出,这个url有些诡异,出现了各种符号,包括! . 以及空格,但是如果我们将这个url输入到浏览器访问的时候,却是通的。
二、问题定位
根据差异性的规则,上面的url2并没有出现错误,因此问题肯定出在了这些诡异的符号上了,感叹号,空格以及 . ,java也有一个类库正好是做url编码规范的,java.net.URLEncoder,将 url输入即可进行格式化为正常的访问规则,如下:
String url = "www.231124214.com/3214 !..mp3";
url = URLEncoder.encode(url, "UTF-8");//值变为 www.231124214.com%2F3214+%21..mp3
可以看出来上面url的规则已经被转码成为utf-8格式的url,而相应的诡异的符号已经被替换转义。但需要注意的是,规则转义标准化 url 字符串之前,需要将字符串中的 “http://” 这些协议前缀去掉,不然里面的 : 和 // 同样会被转义,这样格式化出来的url依旧不能用。
当然除了上述使用url encoder的做法,我发现还可以使用简单粗暴的方式去格式化不规则的url,将这些不规则的url直接输入至浏览器,浏览器会对这些不规则的url中的符号进行转义,比如我们的 “www.231124214.com/3214 !..mp3” 便会被转义为“http://www..com/3214%20!..mp3”,可以看出,只有空格被转义为了 “%20” ,就可以访问了,因此我们也可以直接对url字符串中的空格进行替换即可;
url = url.replaceAll(" ", "%20");
三、解决方案
出现上述异常的结果可能有以下几种:
- 资源的确不存在,报错
- url没有进行格式化,解决方法如上