久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7826|回復: 0
打印 上一主題 下一主題
收起左側

C#多線程Http協(xié)議下載文件

[復制鏈接]
跳轉到指定樓層
樓主
ID:83710 發(fā)表于 2015-6-25 16:36 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本文是參照博客園【CAP&船長】的Demo衍生出來的。

    主要是C#通過
HttpWebRequest類通過Http協(xié)議并調用多線程下載Web資源。

    思路:
    
    1、獲取文件的總大小
    2、設置啟動的線程數目,并分配每個線程的下載的開始位置與下載的字節(jié)數大小
    3、子線程下載成功后保存到臨時文件中
    4、監(jiān)聽所有文件是否全部下載成功
    5、如果所有子線程均下載完成則根據現在Id拼接起來
    6、刪除臨時文件 

    簡單封裝的類: 

    1、新建一個【
CHttpDownload.cs】類
    2、聲明必須的公共屬性與私有屬性以及變量

        private int nThreadNum = 0; // 線程的個數
        private string strUrl = ""; // 下載地址
        private string strSavePath = "";    // 文件保存地址
        private System.Threading.Thread[] threads = null; // 線程數組
        private int[] nStartPosition = null;    // 每個線程的開始地址
        private int[] nFileSize = null; //每個線程下載的大小
        private bool[] bThreadState = null; // 線程下載狀態(tài)
        public bool bHasMerge { get; private set; }    // 是否合并成功
        public long lFileSizeAll { get; private set; }  // 文件總大小
        public int nBufferSize { get; set; }    // 下載文件緩沖區(qū)大小
        private int id = 0;      // 標記線程Id、臨時變量

    2、構造函數 
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="strUrl">文件下載地址Url</param>
        /// <param name="nThreadNum">所需要的線程數</param>
        public CHttpDownload(string strUrl, int nThreadNum)
        {
            /* 初始化下載地址、線程數、緩沖流大小 */ 
            this.strUrl = strUrl;
            this.nThreadNum = nThreadNum;
            this.nBufferSize = 1024;
            Init();
        } 

        /// <summary>
        /// 初始化數據、設置每個線程的開始字節(jié)位置與字節(jié)大小
        /// </summary>
        private void Init()
        {
            threads = new System.Threading.Thread[this.nThreadNum];
            nStartPosition = new int[this.nThreadNum];
            nFileSize = new int[this.nThreadNum];
            bThreadState = new bool[this.nThreadNum];
            bHasMerge = false;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.strUrl);
            lFileSizeAll = request.GetResponse().ContentLength; // 獲取文件的總大小
            request.Abort();    // 端口本次連接

            int nFileNormalSize = (int)lFileSizeAll / nThreadNum;   // 前面線程下載的大小,最后一個線程下載全部
            int nFileLastSize = nFileNormalSize + (int)lFileSizeAll % nThreadNum;   // 最后一個線程下載的大小

            for (int i = 0; i < nThreadNum; i++)
            {
                bThreadState[i] = false;
                nStartPosition[i] = nFileNormalSize * i;
                if (i == nThreadNum - 1)
                {
                    nFileSize[i] = nFileLastSize - 1;
                }
                else
                {
                    nFileSize[i] = nFileNormalSize - 1;
                }
            }
        } 

    3、新建
StartReceive方法,功能為啟動指定一個線程進行下載,并保存到臨時文件中
        /// <summary>
        /// 多線程開始接收
        /// </summary>
        private void StartReceive()
        {
            id++;
            int nId = id - 1;
            string strFileName = "C:\\\\" + nId + ".tmp";
            byte[] buffer = new byte[nBufferSize];
            int nReadSize = 0;  // 標記本次讀到多少個數據

            FileStream fs = new FileStream(strFileName, System.IO.FileMode.Create);
            Stream s = null;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.strUrl);
                request.AddRange(nStartPosition[nId], nStartPosition[nId] + nFileSize[nId]);    // 設置流的開始位置與結束位置
                s = request.GetResponse().GetResponseStream();
                nReadSize = s.Read(buffer, 0, nBufferSize);
                while (nReadSize > 0)
                {
                    fs.Write(buffer, 0, nReadSize);
                    nReadSize = s.Read(buffer, 0, nBufferSize);
                }
                fs.Close();
                s.Close();
            }
            catch (Exception ex)
            {
            }
            bThreadState[nId] = true;
        } 

    4、新建
MergeFiles方法,功能為當所有線程完成下載后進行文件合并保存、并刪除臨時文件
        
/// <summary>
        /// 合并文件 
        /// </summary>
        private void MergeFiles()
        {
            while (true)    // 驗證所有線程是否全部接收完畢
            {
                bHasMerge = true;
                for (int i = 0; i < nThreadNum; i++)
                {
                    if (bThreadState[i] == false)
                    {
                        bHasMerge = false;
                        System.Threading.Thread.Sleep(100);
                        break;
                    }
                }
                if (bHasMerge == true)
                {
                    break;
                }
            }

            int nReadSize;
            byte[] bytes = new byte[nBufferSize];
            FileStream fs = new FileStream(strSavePath, FileMode.Create);
            FileStream fsTmp = null;
            for (int i = 0; i < nThreadNum; i++)
            {
                fsTmp = new FileStream("C:\\\\" + i + ".tmp", FileMode.Open);
                while (true)
                {
                    nReadSize = fsTmp.Read(bytes, 0, nBufferSize);
                    if (nReadSize > 0)
                    {
                        fs.Write(bytes, 0, nReadSize);
                    }
                    else
                    {
                        break;
                    }
                }
                fsTmp.Close();
                if (File.Exists("C:\\\\" + i + ".tmp")) // 如果臨時文件存在則刪除
                {
                    File.Delete("C:\\\\" + i + ".tmp");
                }
            }
            fs.Close();
        }  

    5、新建
StartDownload方法,為客戶調用多線程下載的方法
        /// <summary>
        /// 開始下載文件
        /// </summary>
        /// <param name="strSaveFile">文件的保存地址</param>
        public void StartDownload(string strSaveFile)
        {
            this.strSavePath = strSaveFile;
            for (int i = 0; i < nThreadNum; i++)
            {
                threads[i] = new System.Threading.Thread(new System.Threading.ThreadStart(StartReceive));
                threads[i].Start();
            }
            System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(MergeFiles));
            t.Start();
        }  

    下載地址:http://www.msdn.top/documents/asp.net/
HttpDownload.zip
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人亚洲一区 | 欧美一级片黄色 | 国产视频一区二区在线观看 | 国产精品久久久久久网站 | 国产精品不卡 | 国产成人av免费看 | 亚洲精品888| 日韩精品一区二区三区高清免费 | 国产成人精品亚洲日本在线观看 | 干狠狠| 91综合网 | 黄网免费看 | 手机在线观看 | 欧美激情亚洲 | 欧美日韩高清在线一区 | 亚洲国产精久久久久久久 | 亚洲视频在线播放 | 日韩一区二区三区精品 | 日韩中文字幕网 | 日韩视频一区二区三区 | 国产一区二区三区不卡av | 狠狠撸在线视频 | 亚洲一区av | 亚洲国产精品网站 | 高清人人天天夜夜曰狠狠狠狠 | 91偷拍精品一区二区三区 | 国产免费a视频 | 久久最新 | h视频在线播放 | 91亚洲国产成人精品一区二三 | 伊人电影院av | 亚洲成人午夜电影 | 国产精品国产精品国产专区不卡 | 日韩在线小视频 | 91一区二区三区 | 影音先锋中文字幕在线观看 | 中文字幕亚洲免费 | 国产成人a亚洲精品 | 国产一区三区在线 | 精品国产一区二区三区免费 | 国产激情综合五月久久 |