解决联网下载服务端返回405问题

最近遇到了一个问题,在项目中有一个启动页广告图片下载的功能,之前能够正常下载,由于这个版本遇到了运营商DNS劫持的问题,服务端要调整图片的下载路径,也就是改变了图片的链接地址。修改地址之后下载就出现异常了,经过断点调试发现http请求的返回码为405,查了一下405的意思。

405 Method Not Allowed(不允许使用的方法) 不支持该Request的方法。

那么我们就知道突破点了,只需要设置正确的请求方法就可以解决问题。原本的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private void downloadImage(SplashBean splashBean) {
for (final SplashImage splashImage : splashBean.data.list) {
String name = URLUtil.guessFileName(splashImage.image, "Content-Disposition", null);
if (!TextUtils.isEmpty(splashImage.image)) {
InputStream is = null;
FileOutputStream fileOutputStream = null;
try {
URL url = new URL(splashImage.image);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
conn.setDoOutput(true);
if (HttpURLConnection.HTTP_OK != conn.getResponseCode()) {
Log2345.d(TAG, "连接异常---responseCode = " + conn.getResponseCode());
return;
}
is = conn.getInputStream();
File imageFile = new File(StorageUtils.getCacheDirectory(AllianceApplication.appContext), name);
fileOutputStream = new FileOutputStream(imageFile);
byte[] buffer = new byte[16 * 1024];
int read;
while ((read = is.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
is.close();
fileOutputStream.close();
/**
* 对比文件MD5值
*/
String md5 = GetMD5.getMd5ByFile(imageFile);
Log2345.d(TAG, "MD5对比:" + md5 + "--" + splashImage.md5);
if (md5.equals(splashImage.md5)) {
files.add(imageFile);
}
if (files.size() == splashBean.data.list.size()) {
Log2345.d(TAG, "file.size = " + files.size());
SharedPreferencesUtils.setSplashVersion(splashBean.data.version);
}
SharedPreferencesUtils.setSplashInfo(JSON.toJSONString(splashBean));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

通过抓包发现发送出去的请求为 POST 请求,这点就有点奇怪了,HttpURLConnection 默认的请求方法应该是 GET 求,在这里我并没有设置请求方法为什么抓包看到的是 POST 请求呢?于是在 StackOverFlow 上找到了原因。

StackOverFlow

看字面的意思是说如果调用了 setDoOutput(true) 这个方法的话,默认的 GET 请求会改变为 POST 请求,因为 GET 请求是没有 request body 的。这就解释了之前为什么没有设置请求方法默认应该是 GET 请求,抓包缺看到的是 POST 请求了。那么只需要修改一下代码问题就解决了。

1
2
3
4
5
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");//设置请求方法为 GET 请求
conn.setUseCaches(false);
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);

如上代码,删除掉 setDoOutput(true) 这个方法即可。这个时候问题已经解决了,请求返回码为 200 ,图片下载成功~

我知道一般人都不会点,但是帅的人一定会点!