最近遇到了一个问题,在项目中有一个启动页广告图片下载的功能,之前能够正常下载,由于这个版本遇到了运营商DNS劫持的问题,服务端要调整图片的下载路径,也就是改变了图片的链接地址。修改地址之后下载就出现异常了,经过断点调试发现http请求的返回码为405,查了一下405的意思。
405 Method Not Allowed(不允许使用的方法) 不支持该Request的方法。
那么我们就知道突破点了,只需要设置正确的请求方法就可以解决问题。 
 原本的代码如下:
 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 上找到了原因。

看字面的意思是说如果调用了conn.setDoOutput(true)这个方法的话,默认的 GET 请求会改变为 POST 请求,因为 GET 请求是没有 request body 的。这就解释了之前为什么没有设置请求方法默认应该是 GET 请求,抓包缺看到的是 POST 请求了。那么只需要修改一下代码问题就解决了。
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");//设置请求方法为 GET 请求conn.setUseCaches(false);conn.setReadTimeout(5000);conn.setConnectTimeout(5000);如上代码,删除掉setDoOutput(true)这个方法即可。这个时候问题已经解决了,请求返回码为 200 ,图片下载成功~
















