URL由http到https重定向,URLConnection下载失败

参考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;
    }
}
`
文章目录
|