1. 程式人生 > >http檔案批量多執行緒下載之winform

http檔案批量多執行緒下載之winform

這裡簡單的介紹一種從http獲取檔案然後下載到本地的方法,開始我用單執行緒下載,檔案多的情況下速度太慢了,後來就採用多執行緒,這裡琢磨了好久才整出來一個。這裡的部分程式碼是在部落格園找到的,具體是在哪裡不是很清楚了,搜尋關鍵詞大概是http下載檔案,感謝下。

1.關於多執行緒的思路,檔案下載執行緒,日誌記錄執行緒(使用txt記錄下載檔案日誌),UI執行緒。每個執行緒獨立執行,互不干擾。

(1)這裡說明下為什麼要給UI單獨一個執行緒,主要是因為檔案數量太多的時候,如果這個執行緒是和檔案下載執行緒和在一起的時候,我稍微一動下winform的介面,程式就會卡死,直到程式結束,我表示我已經登出了好多次電腦了。大哭

(2)關於日誌記錄執行緒,因為檔案下載是多執行緒,我這裡就不能把日誌記錄在檔案下載執行緒裡面,不然幾個執行緒一起佔用txt的檔案讀寫。這裡會打架的。

(3)關於檔案下載執行緒,這裡比較簡單了,我啟用了十個執行緒做檔案下載,每個檔案下載單獨的使用一個執行緒,執行緒完了之後繼續下一個任務進行下載。這裡我測試了下,十個執行緒下載速度還是比較理想的,記憶體使用也不是很大,但是這樣可能很佔用伺服器IO記憶體,還是要稍微注意點的,執行緒不要太多了,影響網站的訪問就不是很好了。

不說了 貼程式碼

private bool flag = true;//程序識別符號 
        private int n = 0;//程序記錄數量
        private List<string> list=new List<string>(); //日誌記錄臨時表

//初始化程式碼
public HttpDownloadFile()
        {
            InitializeComponent();
            HttpDownloadFile.CheckForIllegalCrossThreadCalls = false;//這裡必須設定,忘記是做啥用的,大家用的時候可以先不設定,看是報什麼錯誤先
        }
點選按鈕進行檔案下載
private void button1_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(main);
            th.Start();//啟動檔案下載主執行緒
            Thread thtxt = new Thread(writeTxt);
            thtxt.Start();//啟動日誌記錄執行緒
            
        }

日誌執行緒函式說明:
protected void writeTxt() {
            while (true)
            {
                List<string> templist = new List<string>(list);//將list複製到templist
                foreach (string msg in templist)
                {
                    string transferFile = textBox3.Text.Trim();
                    DateTime dt = DateTime.Now;
                    string str;
                    str = msg;
                    StreamWriter sw = new StreamWriter(transferFile + dt.Year + "" + dt.Month + "" + dt.Day + "log.txt", true);
                    sw.WriteLine(dt.ToString() + ":" + str);
                    sw.Close();//寫入 
                    list.Remove(msg);
                }
                templist = new List<string>();
            }
        }

檔案下載主執行緒:
private void main() {
            DateTime dt = DateTime.Now;//開始接收時間   
            label5.Text = dt.ToString();
            List<string> list = new List<string>();
            DataSet ds = new DataSet();
            //從資料庫獲取檔案路徑
            if (checkBox1.Checked)
            {
                ds = Dal.DalDatebase.getUrl(textBox2.Text.Trim());
            }
            else {
                ds = Dal.DalDatebase.getUrl(textBox2.Text.Trim(),1);
            }
            DataRowCollection drc = ds.Tables[0].Rows;
            textBox4.Text = drc.Count.ToString();
            int i = 0;            
            string transferFile = textBox3.Text.Trim();
            while (flag)
            {
                if (i == drc.Count) {
                    flag = false;
                }
                if (n < 10)
                {
                    string tempurl = drc[i]["url"].ToString();
                    string fileName = tempurl.Split('/')[tempurl.Split('/').Length - 1];
                    ParameterizedThreadStart hbStart = new ParameterizedThreadStart(GetFile);
                    Thread hbth = new Thread(hbStart);
                    conData con = new conData();
                    con.fileName = fileName;
                    con.i = i;
                    con.transferFile = transferFile;
                    con.url = tempurl;
                    object ur = con;
                    hbth.Start(ur);
                    n++;//執行緒數
                    i++;//資料庫獲取的資料增量
                }
                
            }
            if (n == 0)//執行緒結束之後彈出檔案接收完畢
            {
                MessageBox.Show("檔案接收完畢");
                dt = DateTime.Now;//開始接收時間   
                label5.Text = dt.ToString();
            }
        }

下載檔案程式碼:
private void GetFile(object str)
        {
            conData con = (conData)str;
            try
            {                            
                listBox1.Items.Add("檔案(" + con.i + "):" + con.fileName + "開始接收");
                FileStream fs = new FileStream(con.transferFile + con.fileName, System.IO.FileMode.Create);
                try
                {
                    HttpWebRequest request= (HttpWebRequest)HttpWebRequest.Create(con.url);
                    long filesize = request.GetResponse().ContentLength;//取得目標檔案的長度   
                    if (filesize > 0)
                    {
                        byte[] nbytes = new byte[512];
                        System.IO.Stream ns = request.GetResponse().GetResponseStream();//獲得接收流   
                        int nreadsize = ns.Read(nbytes, 0, 512);
                        while (nreadsize > 0)
                        {
                            fs.Write(nbytes, 0, nreadsize);
                            nreadsize = ns.Read(nbytes, 0, 512);
                        }
                        fs.Close();
                        ns.Close();
                    }
                    request.Abort();
                }
                catch (Exception er)
                {
                    listBox1.Items.Add("檔案(" + con.i + "):" + con.fileName + "接收失敗,錯誤資訊:"+er.Message);
                    fs.Close();
                }
                listBox1.Items.Add("檔案(" + con.i + "):" + con.fileName + "接收完畢!");
                listBox1.SelectedIndex = listBox1.Items.Count - 1;
                list.Add("檔案(" + con.i + "):" + con.fileName + "接收完畢!");
            }
            catch (Exception e)
            {
                list.Add("檔案(" + con.i + "):" + con.fileName + "接收失敗!錯誤資訊:" + e.Message);
            }
            n--;
        }
多執行緒傳參的時候是物件形式,我把多個物件寫成了一個class,方便傳參
public class conData {
        public string transferFile { set; get; }
        public string url { set; get; }
        public string fileName { set; get; }
        public int i { set; get; }
    }

private void button2_Click(object sender, EventArgs e)
        {
            flag = false;//原有的執行緒繼續執行,不會增加新的程序  
            this.Close();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Dispose();
            System.Environment.Exit(0);  //結束所有執行緒
            this.Close();
        }
好了 也在這裡程式碼也基本結束了。如果大家有什麼疑問或者有什麼改進的意見,歡迎留言。做就要做的更好。

相關推薦

http檔案批量執行下載winform

這裡簡單的介紹一種從http獲取檔案然後下載到本地的方法,開始我用單執行緒下載,檔案多的情況下速度太慢了,後來就採用多執行緒,這裡琢磨了好久才整出來一個。這裡的部分程式碼是在部落格園找到的,具體是在哪裡不是很清楚了,搜尋關鍵詞大概是http下載檔案,感謝下。 1.關於多執行

通過HTTP協議實現執行下載

1. 基本原理,每條執行緒從檔案不同的位置開始下載,最後合併出完整的資料。  2. 使用多執行緒下載的好處      下載速度快。為什麼呢?很好理解,以往我是一條執行緒在伺服器上下載。也就是說,對應在伺服器上,有一個我的下載執行緒存在。      這時候肯定不只我一個人

JavaIo——運用RandomAccessFile實現檔案執行下載

文章轉載自:http://blog.csdn.net/akon_vm/article/details/7429245 利用RandomAccessFile實現檔案的多執行緒下載,即多執行緒下載一個檔案時,將檔案分成幾塊,每塊用不同的執行緒進行下載。下面是一個利用多執行緒在寫

java網路程式設計下載檔案通過執行分塊下載(二)

importjava.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConn

java執行下載http協議檔案

package com.wild.http; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream

ios開發網路-大檔案執行斷點下載

說明:本文介紹多執行緒斷點續傳。專案中使用了蘋果自帶的類,實現了同時開啟多條執行緒下載一個較大的檔案。 因為實現過程較為複雜, 實現思路:下載 開始,建立一個與要下載檔案大小相同的檔案(如果要下載100M,那麼就在沙盒建立一個100M的檔案,然後計算每一段的下載量,開啟多條執行緒下載各段的資料,分

Android原生下載(下篇)檔案下載+執行下載

零、前言 1.上篇實現了單執行緒的單檔案下載,本篇將講述多個檔案的多執行緒下載,在此之前希望你先弄懂上篇 2.本篇將用到上篇之外的技術: 多執行緒、執行緒池(簡)、RecyclerView、資料庫多執行緒訪問下的注意點、volatile AtomicLong(簡) 最終靜態的效果

風火程式設計--python執行下載檔案

多執行緒下載檔案 出現異常的執行緒會自動重新下載, 所有的進度會在同一位置輪換顯示 import os import datetime from urllib import request url_list = ["url1","url2","url3"

axel: 執行下載工具,下載檔案時可以替代curl、wget

 Axel 是 Linux 下一個不錯的HTTP/FTP高速下載工具。支援多執行緒下載、斷點續傳,且可以從多個地址或者從一個地址的多個連線來下載同一個檔案。適合網速不給力時多執行緒下載提高下載速度。比如在國內VPS或伺服器上下載lnmp一鍵安裝包用Axel就比wget快。opti

java使用 網路連線+RandomAccessFile + io 執行實現執行下載檔案並顯示實時網速

下載檔案的時候,一個大檔案切成很多片,用多執行緒下載,速度會快很多 閱讀程式碼的時候注意檢視程式碼裡面的註釋 想用多執行緒下載檔案,則, 第一:得了解  RandomAccessFile  類,這是個隨機訪問檔案類,裡面可以設定 訪問的 開始地址和結束地址,且該類可讀可

執行下載一個檔案

瞭解了這麼多與執行緒相關的知識,那麼我們也要實戰一下了(在學習本篇知識之前,如果對java中的網路基礎連結不太熟悉的,建議先去學一下java網路程式設計,再來看本文章。) 因為本篇是多執行緒下載的demo,所以就直接附上程式碼,裡面都寫好了註釋,不影響對本篇的學習。

Deepin學習筆記---如何執行下載網路檔案

**** 命令列下載網路檔案* 當時看到師兄用多執行緒下載一個檔案,簡直帥呆了,然後自己偷摸學習了一下,很爽,這邊推薦兩個命令列下載網路檔案的方法,前提是要有下載連結哦! 一、 1.wget下載方式 wget http://www.linuxsense.or

Android實現執行下載檔案,支援斷點

本篇部落格主要介紹多執行緒去下載檔案,以下載多個app為例。不管去下在app,音視訊等檔案,實現起來都一樣。篇幅有點長,先貼張美女圖看看 正在下載的效果圖 下載完成效果圖 小編的下載路徑是放在sd卡的絕對路徑中,方便驗證! 工程目錄圖 介紹下每

Java執行下載網路檔案

新建一個JavaGUI介面 package Download; import java.awt.EventQueue; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.Action

Java jdbc批量執行讀取CVS檔案入庫效能優化篇

在寫完上一篇文章之後,在使用過程中慢慢發現一些問題,比如說資料入庫很慢,10W的資料分10個檔案入庫大概需要兩三分鐘,如下圖 這是我忍受不了的,所以我尋思著如何優化該程式,提高入庫效能。因此我對JDBC資料入庫的幾種方法做了一個對比,在大量的實驗下,發現瞭

C++執行(C++11 thread.h檔案實現執行

轉載自: 與 C++11 多執行緒相關的標頭檔案 C++11 新標準中引入了四個標頭檔案來支援多執行緒程式設計,他們分別是<atomic> ,<thread>,<mutex>,<condition_variable>和&l

Android 實現執行下載檔案+斷點續傳

                            Android 多執行緒下載檔案+斷點續傳       在專案快要結束的時候,發現了app沒有版本更新的功能,於是找到一些過去的資料,在app上應用完成了版本更新,現在記錄一下apk的下載,也就是如何通過多執行緒將ap

java執行下載檔案和斷點下載

多執行緒,斷點下載檔案 import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOExcept

iOS【執行網路圖片下載框架SDWebImage】

效果: 程式碼: - (NSArray *)apps { if (!_apps) { NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pat

HttpURLConnection斷點續傳(執行下載

public class MainActivity extends Activity { private static final int PROCESSING = 1; private static final int FAILURE = -1; private EditText pat