技术开发 频道

C#实现HTTP下的多线程文件传输

    定义一个HttpFile类,用于管理接收线程,其代码如下:

public class HttpFile {  public Form1 formm;  public int threadh;//线程代号  public string filename;//文件名  public string strUrl;//接收文件的URL  public FileStream fs;  public HttpWebRequest request;  public System.IO.Stream ns;  public byte[] nbytes;//接收缓冲区  public int nreadsize;//接收字节数  public HttpFile(Form1 form,int thread)//构造方法  {   formm=form;   threadh=thread;  }  ~HttpFile()//析构方法  {   formm.Dispose ();  }  public void receive()//接收线程  {   filename=formm.filenamew[threadh];   strUrl=formm.strurl;   ns=null;   nbytes= new byte[512];   nreadsize=0;   formm.listBox1 .Items .Add ("线程"+threadh.ToString ()+"开始接收");   fs=new FileStream (filename,System.IO.FileMode.Create);   try   {    request=(HttpWebRequest)HttpWebRequest.Create (strUrl);    //接收的起始位置及接收的长度    request.AddRange(formm.filestartw [threadh],    formm.filestartw [threadh]+formm.filesizew [threadh]);    ns=request.GetResponse ().GetResponseStream ();//获得接收流    nreadsize=ns.Read (nbytes,0,512);    while (nreadsize>0)    {     fs.Write (nbytes,0,nreadsize);     nreadsize=ns.Read (nbytes,0,512);     formm.listBox1 .Items .Add ("线程"+threadh.ToString ()+"正在接收");    }    fs.Close();    ns.Close ();   }   catch (Exception er)   {    MessageBox.Show (er.Message );    fs.Close();   }   formm.listBox1 .Items.Add ("进程"+threadh.ToString ()+"接收完毕!");   formm.threadw[threadh]=true;  } }
    该类和Form1类处于统一命名空间,但不包含在Form1类中。下面定义“开始接收”按钮控件的事件响应函数:

private void button1_Click(object sender, System.EventArgs e) {  DateTime dt=DateTime.Now;//开始接收时间  textBox1.Text =dt.ToString ();  strurl=textBox2.Text .Trim ().ToString ();  HttpWebRequest request;  long filesize=0;  try  {   request=(HttpWebRequest)HttpWebRequest.Create (strurl);   filesize=request.GetResponse ().ContentLength;//取得目标文件的长度   request.Abort ();  }  catch (Exception er)  {   MessageBox.Show (er.Message );  }  // 接收线程数  thread=Convert.ToInt32 (textBox4.Text .Trim().ToString (),10);  //根据线程数初始化数组  threadw=new bool [thread];  filenamew=new string [thread];  filestartw=new int [thread];  filesizew=new int[thread];  //计算每个线程应该接收文件的大小  int filethread=(int)filesize/thread;//平均分配  int filethreade=filethread+(int)filesize%thread;//剩余部分由最后一个线程完成  //为数组赋值  for (int i=0;i<thread;i++)  {   threadw[i]=false;//每个线程状态的初始值为假   filenamew[i]=i.ToString ()+".dat";//每个线程接收文件的临时文件名   if (i<thread-1)   {    filestartw[i]=filethread*i;//每个线程接收文件的起始点    filesizew[i]=filethread-1;//每个线程接收文件的长度   }   else   {    filestartw[i]=filethread*i;    filesizew[i]=filethreade-1;   }  }  //定义线程数组,启动接收线程  Thread[] threadk=new Thread [thread];  HttpFile[] httpfile=new HttpFile [thread];  for (int j=0;j<thread;j++)  {   httpfile[j]=new HttpFile(this,j);   threadk[j]=new Thread(new ThreadStart (httpfile[j].receive ));   threadk[j].Start ();  }  //启动合并各线程接收的文件线程  Thread hbth=new Thread (new ThreadStart (hbfile));  hbth.Start (); }
    合并文件的线程hbfile定义在Form1类中,定义如下:

public void hbfile() {  while (true)//等待  {   hb=true;   for (int i=0;i<thread;i++)   {    if (threadw[i]==false)//有未结束线程,等待    {     hb=false;     Thread.Sleep (100);     break;    }   }   if (hb==true)//所有线程均已结束,停止等待,   {    break;   }  }  FileStream fs;//开始合并  FileStream fstemp;  int readfile;  byte[] bytes=new byte[512];  fs=new FileStream (textBox3.Text .Trim ().ToString (),System.IO.FileMode.Create);  for (int k=0;k<thread;k++)  {   fstemp=new FileStream (filenamew[k],System.IO.FileMode .Open);   while (true)   {    readfile=fstemp.Read (bytes,0,512);    if (readfile>0)    {     fs.Write (bytes,0,readfile);    }    else    {     break;    }   }   fstemp.Close ();  }  fs.Close ();  DateTime dt=DateTime.Now;  textBox1.Text =dt.ToString ();//结束时间  MessageBox.Show ("接收完毕!!!"); }
    至此,一个多线程下载文件的程序就大功告成了,注意在输入本地文件名时,应按如下格式输入:“c:\\test\\httpftp\\bin\\d.htm”,因”\”后的字符在C#中是转义字符,线程数并非越大越好,一般5个线程就可以了,该程序在Visual Studio.Net 2002开发环境及Windows xp 操作系统上通过。
0
相关文章