参考1:分析为何使用URLConnection下载文件失败的原因
参考2:具体解决HttpURLConnection重定向问题参考代码
拷贝自参考1文章部分:(防止源网页不可用,感謝原作者填坑)
URLConnection从HTTP重定向到HTTPS
也不知什么原因,公司项目的服务端一直在吸引着大波攻击,于是服务端的同学打算把所有HTTP的请求都换为HTTPS,他们决定兼容旧版本于是就将之前的所有HTTP请求全部重定向到另一个HTTPS请求。
项目请求框架搭建初期,考虑到应用也不会使用太复杂的请求模式,于是就简单使用URLConnection完成服务端交互。服务端一修改,全部请求都失败了。虽然URLConnection有是否遵循重定向开关(setInstanceFollowRedirects),其默认就是开启的,即便你再强制其打开,也是没有用,问题依旧。找了大量资料,其实问题的关键点不是重定向而是从HTTP重定向到HTTPS,关键点就在URLConnection的两个子类上。
HttpURLConnection与HttpsURLConnection
HttpURLConnection为URLConnection的子类,而HttpsURLConnection为HttpURLConnection的子类,在HttpURLConnection基础上对HTTPS进行支持。
URLConnection通常使用URL的openConnection()方法获得,而URL是根据其是否为Https开头来打开一个HttpURLConnection还是HttpsURLConnection。
而当URLConnection进行connect()时,遇到了重定向,如果打开了遵循重定向,那么其会获取重定向的地址,然后尝试连接这个地址。值得注意的是,这时候并不是使用新的链接地址重新openConnection()一个URLConnection,而是直接尝试连接这个重定向的地址,否则也就不存在以上的Bug了。
于是理论上分析,HTTP重定向到HTTP是不存在问题的,HTTPS重定向到HTTPS也是不存在问题的,而HTTP与HTTPS之间的重定向,那么就很可能会有问题了。HTTP重定向到HTTPS,URLConnection会将重定向的HTTPS以HTTP方式继续提交,那么服务端肯定是认为你是错误的提交方式;同理,HTTPS重定向HTTP也一样。
问题解决
使用URLConnection抓取到重定向,就使用重定向的地址重新人为openConnection()一个新的URLConnection重新请求。
使用第三方请求框架,如OKHttp。
具体项目具体分析,方法一是可行的,但是处理起来就很麻烦了。而方案二则更可选,因为URLConnection与OKHttp用法其实差不了多远
##URLConnection支持302重定向,Demo
`
package com.cuncaojin.myapplication;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private ProgressDialog mProgressDialog;
private int mContentLength;
private long mCurrentLength;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
if (mContentLength <= 0) {
mProgressDialog.setProgress(0);
mTextView.setText(0);
} else {
int p = (int) (mCurrentLength * 100 / mContentLength);
mProgressDialog.setProgress(p);
mTextView.setText(p + "");
}
break;
case 1:
Toast.makeText(MainActivity.this, "Down Finished!", Toast.LENGTH_LONG).show();
mProgressDialog.dismiss();
mProgressDialog = null;
break;
case 2:
mProgressDialog.show();
break;
default:
break;
}
}
};
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textView);
}
public void click(View view) {
String url = "http://www.chinaums.com/static/ums2013/chinaums/app/download/ppplugin.apk";
downLoadFile(url, new File(Environment.getExternalStorageDirectory(), url.substring(url.lastIndexOf("/") + 1)));
}
private void downLoadFile(final String url, final File destFile) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setMax(100);
mProgressDialog.incrementProgressBy(1);
mProgressDialog.setProgress(0);
new Thread(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(2);
BufferedInputStream in = null;
BufferedOutputStream out = null;
HttpURLConnection conn = null;
try {
conn = getHttpURLConnection(conn, url);
int times = 5;
while (conn.getResponseCode() != HttpURLConnection.HTTP_OK && times-- > 0) {
Log.e("tag", "----------ResponseCode: " + conn.getResponseCode()+", URL:" + url);
String url = conn.getHeaderField("Location");
conn = getHttpURLConnection(conn, url);
Log.e("tag", "----------NextURL:" + url);
}
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
mContentLength = conn.getContentLength();
in = new BufferedInputStream(conn.getInputStream());
out = new BufferedOutputStream(new FileOutputStream(destFile));
byte[] buffer = new byte[1024];
int len = 0;
mCurrentLength = 0;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
mCurrentLength += len;
mHandler.sendEmptyMessage(0);
}
out.flush();
mHandler.sendEmptyMessage(1);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
@NonNull
private HttpURLConnection getHttpURLConnection(HttpURLConnection conn, String url) throws IOException {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(8000);
conn.setReadTimeout(8000);
conn.setInstanceFollowRedirects(false);//不支持重定向
conn.connect();
return conn;
}
}
`