HttpURLConnection實現多線程下載資源contentLength()

package com.example.tyxiong.myapplication;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;


/*
*
 * Android 網絡應用.
 *  3句概述:1 Android支持JDK的TCP/IP UDP的網絡通信API.即可用ServiceSocket Socket來建立基於TCP/IP協議的網絡通信;
 *           也可以用DatagramSocket Dategrampacket MuliticastSocket來建立基於UDP協議的網絡通信.
 *         2 Android支持JDK的URL URLConnection等網絡通信.
 *         3 Android內置了HttpClient,方便的發送HTTP請求,簡化了與網站間的交互.(可惜沒有內置Web Service支持./有ksoap2-android項目)
 *
 *         IP協議:實現計算機發送接收分組數據.
 *         TCP協議:提供可靠無差錯的通信服務. 端對端的協議(爲兩個通信實體之間通信起到了重要作用), 重發機制(接收方收到數據,有應答,若無則發送方重發數據)
 *         TCP IP功能互補,通常兩者結合使用,統稱TCP/IP協議.
 *         TCP/IP協議通信建立過程: 服務器端(主動)接收客戶端連接請求(accept()方法),當有客戶端(Socket)發送連接請求時,
 *         方法返回與之對應的Socket;通信鏈路建立.主客消失,可通過Socket通信.
 *         使用步驟4步:
 *          1 服務器端創建ServiceSocket對象,指定端口(大於1024) 默認IP
 *          2 對象的實例方法accept(),接收客戶端請求.阻塞線程,有請求時方法返回Socket對象
 *          3 客戶端創建Socket對象,連接到指定的服務器端口 new Socket(remoteAddress,port)
 *          4 兩個通信實體可通過Socket通信啦. 有方法getInputStream()/out.. 編碼的問題linux平臺用UTF-8字符集.
 *
 *          注意:android建立網絡連接不允許在UI線程中進行.
 *          設置讀取數據超時(BufferReader readLine()阻塞):Socket有方法setSoTimeout(),超時可拋異常
 *          設置連接服務器超時:步驟1 建無連接的Socket new Socket() 2 connect()方法設置
 *
 *          網絡通信中多線程:服務器端:由於readLine()會阻塞線程,則每個Socket建立一個線程負責.
 *                          客戶端: 同樣,需要一個線程讀取服務器數據+ 然後主線程負責界面,用戶輸入.
 *
 *
 *          URL,統一資源定位器,能打開URL指定網絡數據的輸入流(讀取) 2個實例方法openStream()/打開連接的輸入流 openURLConnection()/打開應用程序與URL資源間的連接對象
 *          URL組成:協議名,主機名,端口,資源.
 *          讀取網絡資源2步驟:
 *              1 創建URL對象   2openStream()打開資源輸入流,,讀取吧.>>>
 *
     *     URLConnection提交請求:URL對象實例方法openURLConnection()方法->URLConnection對象-->發送請求,獲取數據.
      *     6方法 2+4 設置請求頭字段  setRequestProperty(key,value)設置請求字段的值. addRequestProperty()爲指定key追加value值.
      *                 獲取響應    getContent()/獲取該URLConnection內容
       *                            getHeaderField(string)獲取指定響應頭字段的值
       *                            getInputStream()/URLConnection輸入流,讀取響應
       *                            getOutputStram()/URLConnection輸出流,發送請求參數
       *            使用分4步驟:
       *                   1 URL對象,方法 獲取URLConnection對象
       *                   2 設置URLConnection參數及請求字段屬性
       *                   3 若發送GET請求,直接connect()方法建立實際連接. Post請求則要打開URLConnection的輸出流,先發送請求參數.
       *                   4 遠程資源可用,用獲取響應方法讀取資源.
       *   注意:*****若既要發送請求,又要讀取響應內容時,先發,再讀.POST請求
       *        ****若需發送POST請求,必須設置 setDoOutput(true) setDoInput(true)頭字段.
       *        ****用完關閉流.try/catch/final
       *

      *    HttpURLConnection URLConnection子類,增強,爲Http訪問提供了不4個便捷方法
      *                         1 getResponseCode()//獲取服務器響應代碼
      *                         2 getResponseMessage()//響應消息
      *                         3 getRequestMethod()//獲取發送請求的方法
      *                         4 setRequestMethoe()//設置發送請求的方法.
      *
      *  多線程下載5步:
      *         1 URL對象
      *         2 獲取URL對象指定資源數據大小(getContentLength())
      *         3 本地建立與資源相同大小空文件
      *         4 平分資源計算每條線程下載的字節部分.
      *         5 創建,啓動多條線程下載.
      *
      *
      * HttpClient :1概述:Apache組織的項目,Android也內置了HttpClient支持.簡單的Http客戶端,用於發送HTTP請求
      * 接收響應,增強版本的HttpURLConnection.使用5步:  3個對象 3個方法
      *     1 創建HttpClient對象
      *     2 若發送GET請求--HttpGet對象     POST請求--HttpPost對象
      *     3 設置發送請求參數,,,可用setParams()/setEntity()
      *     4 HttpClient對象execute()方法發送請求.該方法返回HttpResponse對象
      *     5 HttpResponse對象 getEntity()方法,,獲取響應內容.
      *
      *
      *
     *
 *
 *
 *  HttpURLConnection URLConnection子類,增強,爲Http訪問提供了不4個便捷方法
      *                         1 getResponseCode()//獲取服務器響應代碼
      *                         2 getResponseMessage()//響應消息
      *                         3 getRequestMethod()//獲取發送請求的方法
      *                         4 setRequestMethoe()//設置發送請求的方法.
  * */


public class MainActivity extends Activity {

    EditText show;
    Handler handler;
    private Thread thread;
    EditText fileName;
    EditText threadCount;
    ProgressDialog progressDialog;
    private int progress;
    private int MAX = 100;
    DownUtils downUtils;
    String url;
    String path;
    int count;
    public void send(View view) {//向服務器發送數據....
        url = show.getText().toString();
        path = fileName.getText().toString();
        count = Integer.parseInt(threadCount.getText().toString().trim());


        progressDialog.show();
        thread.start();
    }//發送GET請求...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        show = (EditText) findViewById(R.id.show);

        fileName = (EditText) findViewById(R.id.fileName);
        threadCount = (EditText) findViewById(R.id.count);

        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("下載");
        progressDialog.setIndeterminate(false);
        progressDialog.setCancelable(false);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setMessage("正在下載...");
        progressDialog.setMax(MAX);

        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 0x11) {
                    progressDialog.setProgress(progress);
                }
            }
        };

        thread = new Thread() {
            @Override
            public void run() {
                downUtils = new DownUtils(url, path, count);
                downUtils.sendGet();
                while (progress < MAX) {
                    float position = downUtils.getProgress();
                    progress = (int) (MAX * position);
                    try {
                        sleep(1 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    handler.sendEmptyMessage(0x11);
                }
                progressDialog.dismiss();
            }
        };


    }
}

class DownUtils {
String link;
   /*  "http://p.gdown.baidu.com/ab67d1f87dda5edd22d919fc5a33bad644220b671bb3bb17fd6f8849a61ed2c3c7e9c44f13348ef75f6bcbdb8cdc5c867bcf7dd31f353abeb47a285ab0b588c5c0df7dcdbcf395acd80b500258e99d064d92bac54af82bd95b7553bd86e2bc83ce217398cfb18bd8fd5e6a6f506db32f75cb5e965207230404b400a9fdd2fdc8e20c4215f9fde290e5b22eed14479ddd43a35e954f30c2e8ed119b7239a659fbf59390a45f51edaab818ef4eeb14a4011dd043f84f4b70f4d49f8a5b0571d5b1d8bdb84b2d49d3687d5b43e0fe513b59f3beef45c6121fd0088e20ad370cb22e02207716b95d8f627a5fe9d79f99b06852651f73c5d0e63476b8148506a88909fb0947b3e5510573632887aeee2e6b871dfe70d2ee93fc2fad2997f2a2845e1f40ac0b9ddbcf4e679cd8b0600f1a93af5774d530038d59a073d1e7f97ef1b488";*/
    String path;
    int COUNT;

    public DownUtils(String link, String path, int COUNT) {
        this.link = link;
        this.path = "/mnt/sdcard/"+path;
        this.COUNT = COUNT;
    }

    ArrayList<DownThread> list = new ArrayList<>();
    int fileSize = 0;
    int subSize = 0;

    public float getProgress() {

        int num = 0;

        for (int i = 0; i < list.size(); i++) {
            num += list.get(i).progress;
        }
        return 1.0f * num / fileSize;

    }

    public void sendGet() {

        RandomAccessFile file = null;
        try {
            final HttpURLConnection urlConnection;
            URL url = new URL(link);
            urlConnection = (HttpURLConnection) url.openConnection();//1獲取與遠程資源的連接.
            urlConnection.setConnectTimeout(10 * 1000);

            urlConnection.setRequestProperty("accept", "*/*");
            urlConnection.setRequestProperty("connection", "Keep-Alive");
            urlConnection.setRequestProperty("charset", "utf-8");//設置請求字段屬性.
            urlConnection.getRequestMethod();
            urlConnection.setRequestMethod("GET");                   //便捷方法設置發送請求方法
            fileSize = urlConnection.getContentLength();
            urlConnection.disconnect();
            file = new RandomAccessFile(path, "rw");
            file.setLength(fileSize);
            Log.w("xxx", "sendGet: 需要下載文件大小" + fileSize);
            subSize = fileSize / COUNT;
            for (int i = 0; i < COUNT; i++) {

                DownThread newThread = new DownThread(i * subSize, subSize);//// TODO: 11/11/2016
                list.add(newThread);
                newThread.start();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                assert file != null;
                file.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    class DownThread extends Thread {
        public int position = 0;
        int length = 0;
        int progress = 0;


        public DownThread(int position, int length) {
            this.position = position;
            this.length = length;

        }


        @Override
        public void run() {

            HttpURLConnection urlConnection;
            URL url;
            try {
                RandomAccessFile randomAccessFile = new RandomAccessFile(path, "rw");
                url = new URL(link);
                urlConnection = (HttpURLConnection) url.openConnection();//1獲取與遠程資源的連接.
                urlConnection.setConnectTimeout(10 * 1000);

                urlConnection.setRequestProperty("accept", "*/*");
                urlConnection.setRequestProperty("connection", "Keep-Alive");
                urlConnection.setRequestProperty("charset", "utf-8");//設置請求字段屬性.
                urlConnection.getRequestMethod();
                urlConnection.setRequestMethod("GET");                   //便捷方法設置發送請求方法
                urlConnection.connect();
                InputStream inputStream = urlConnection.getInputStream();
                long j = 0;
                while (j < position) {
                    j += inputStream.skip(position - j);
                }
                randomAccessFile.seek(position);

                int read = 0;
                byte[] buffer = new byte[1024];
                while (progress < length && read != -1) {
                    read = inputStream.read(buffer, 0, buffer.length);
                    randomAccessFile.write(buffer, 0, read);
                    progress += read;
                }

                randomAccessFile.close();
                inputStream.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }


}
 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
![運行效果](http://img.blog.csdn.net/20161112192835504)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章