在了解HTTP断点续传的原理之前,让我们先来了解一下HTTP协议,HTTP协议是一种基于tcp的简单协议,分为请求和回复两种。请求协议是由 客户机(浏览器)向服务器(WEB SERVER)提交请求时发送报文的协议。回复协议是由服务器(web server),向客户机(浏览器)回复报文时的协议。请求和回复协议都由头和体组成。头和体之间以一行空行为分隔。

   以下是一个请求报文与相应的回复报文的例子: 
GET /image/index_r4_c1.jpg HTTP/1.1 
Accept: */* 
Referer: http://192.168.3.120:8080 
Accept-Language: zh-cn 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705) 
Host: 192.168.3.120:8080 
Connection: Keep-Alive

HTTP/1.1 200 OK 
Server: Microsoft-IIS/5.0 
Date: Tue, 24 Jun 2003 05:39:40 GMT 
Content-Type: image/jpeg 
Accept-Ranges: bytes 
Last-Modified: Thu, 23 May 2002 03:05:40 GMT 
ETag: "bec48eb862c21:934" 
Content-Length: 2827

….

  下面我们就来说说"断点续传",顾名思义,断点续传就是在上一次下载时断开的位置开始继续下载。 
在HTTP协议中,可以在请求报文头中加入Range段,来表示客户机希望从何处继续下载。

  比如说从第1024字节开始下载,请求报文如下:

GET /image/index_r4_c1.jpg HTTP/1.1 
Accept: */* 
Referer: http://192.168.3.120:8080 
Accept-Language: zh-cn 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705) 
Host: 192.168.3.120:8080 
Range:bytes=1024- 
Connection: Keep-Alive

  .NET中的相关类

   明白了上面的原理,那么,我们来看看.NET FRAMEWORK中为我们提供了哪些类可以来做这些事。

   完成HTTP请求

System.Net.HttpWebRequest

   HttpWebRequest 类对 WebRequest 中定义的属性和方法提供支持,也对使用户能够直接与使用 HTTP 的服务器交互的附加属性和方法提供支持。

   HttpWebRequest 将发送到 Internet 资源的公共 HTTP
标头值公开为属性,由方法或系统设置。下表包含完整列表。可以将 Headers
属性中的其他标头设置为名称/值对。但是注意,某些公共标头被视为受限制的,它们或者直接由
API公开,或者受到系统保护,不能被更改。Range也属于被保护之列,不过,.NET为开发者提供了更方便的操作,就是
AddRange方法,向请求添加从请求数据的开始处或结束处的特定范围的字节范围标头

   完成文件访问

System.IO.FileStream

   FileStream 对象支持使用Seek方法对文件进行随机访问, Seek
允许将读取/写入位置移动到文件中的任意位置。这是通过字节偏移参考点参数完成的。字节偏移量是相对于查找参考点而言的,该参考点可以是基础文件的开始、
当前位置或结尾,分别由SeekOrigin类的三个属性表示。

   代码实现

   了解了.NET提供的相关的类,那么,我们就可以方便的实现了。

   代码如下:

static void Main(string[] args) 
{

string StrFileName="c:\\aa.zip"; //根据实际情况设置 
string StrUrl="http://www.xxxx.cn/xxxxx.zip "; //根据实际情况设置

//打开上次下载的文件或新建文件 
long lStartPos =0; 
System.IO.FileStream fs; 
if (System.IO.File.Exists(StrFileName)) 

fs= System.IO.File.OpenWrite(StrFileName); 
lStartPos=fs.Length; 
fs.Seek(lStartPos,System.IO.SeekOrigin.Current); //移动文件流中的当前指针 

else 

fs = new System.IO.FileStream(StrFileName,System.IO.FileMode.Create); 
lStartPos =0; 
}

//打开网络连接 
try 

System.Net.HttpWebRequest request =(System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(StrUrl); 
if ( lStartPos>0) 
request.AddRange((int)lStartPos); //设置Range值

//向服务器请求,获得服务器回应数据流 
System.IO.Stream ns= request.GetResponse().GetResponseStream();

byte[] nbytes = new byte[512]; 
int nReadSize=0; 
nReadSize=ns.Read(nbytes,0,512); 
while( nReadSize >0) 

fs.Write(nbytes,0,nReadSize); 
nReadSize=ns.Read(nbytes,0,512); 

fs.Close(); 
ns.Close(); 
Console.WriteLine("下载完成"); 

catch(Exception ex) 

fs.Close(); 
Console.WriteLine("下载过程中出现错误:"+ex.ToString()); 

}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fhbcn/archive/2009/01/15/3789035.aspx

另一个断点续传的代码:

/* .Net/C#: 实现支持断点续传多线程下载的工具类 
 * Reflector 了一下 System.Net.WebClient ,改写或增加了若干: 
 * DownLoad、Upload 相关方法! 
 * 增加了 DataReceive、ExceptionOccurrs 事件 
 */

namespace Microshaoft.Utils 

 using System; 
 using System.IO; 
 using System.Net; 
 using System.Text; 
 using System.Security; 
 using System.Threading; 
 using System.Collections.Specialized;

/// <summary> 
 /// 记录下载的字节位置 
 /// </summary> 
 public class DownLoadState 
 { 
  private string _FileName;

private string _AttachmentName; 
  private int _Position; 
  private string _RequestURL; 
  private string _ResponseURL; 
  private int _Length;

private byte[] _Data;

public string FileName 
  { 
   get 
   { 
    return _FileName; 
   } 
  }

public int Position 
  { 
   get 
   { 
    return _Position; 
   } 
  }

public int Length 
  { 
   get 
   { 
    return _Length; 
   } 
  }

public string AttachmentName 
  { 
   get 
   { 
    return _AttachmentName; 
   } 
  }

public string RequestURL 
  { 
   get 
   { 
    return _RequestURL; 
   } 
  }

public string ResponseURL 
  { 
   get 
   { 
    return _ResponseURL; 
   } 
  }

public byte[] Data 
  { 
   get 
   { 
    return _Data; 
   } 
  }

internal DownLoadState(string RequestURL, string ResponseURL,
string FileName, string AttachmentName, int Position, int Length, byte[]
Data) 
  { 
   this._FileName = FileName; 
   this._RequestURL = RequestURL; 
   this._ResponseURL = ResponseURL; 
   this._AttachmentName = AttachmentName; 
   this._Position = Position; 
   this._Data = Data; 
   this._Length = Length; 
  }

internal DownLoadState(string RequestURL, string ResponseURL,
string FileName, string AttachmentName, int Position, int Length,
ThreadCallbackHandler tch) 
  { 
   this._RequestURL = RequestURL; 
   this._ResponseURL = ResponseURL; 
   this._FileName = FileName; 
   this._AttachmentName = AttachmentName; 
   this._Position = Position; 
   this._Length = Length; 
   this._ThreadCallback = tch; 
  }

internal DownLoadState(string RequestURL, string ResponseURL,
string FileName, string AttachmentName, int Position, int Length) 
  { 
   this._RequestURL = RequestURL; 
   this._ResponseURL = ResponseURL; 
   this._FileName = FileName; 
   this._AttachmentName = AttachmentName; 
   this._Position = Position; 
   this._Length = Length; 
  }

private ThreadCallbackHandler _ThreadCallback;

public HttpWebClient httpWebClient 
  { 
   get 
   { 
    return this._hwc; 
   } 
   set 
   { 
    this._hwc = value; 
   } 
  }

internal Thread thread 
  { 
   get 
   { 
    return _thread; 
   } 
   set 
   { 
    _thread = value; 
   } 
  }

private HttpWebClient _hwc; 
  private Thread _thread;

// 
  internal void StartDownloadFileChunk() 
  { 
   if (this._ThreadCallback != null) 
   { 
    this._ThreadCallback(this._RequestURL, this._FileName, this._Position, this._Length); 
    this._hwc.OnThreadProcess(this._thread); 
   } 
  }

}

//委托代理线程的所执行的方法签名一致 
 public delegate void ThreadCallbackHandler(string S, string s, int I, int i);

//异常处理动作 
 public enum ExceptionActions 
 { 
  Throw, 
  CancelAll, 
  Ignore, 
  Retry 
 }

/// <summary> 
 /// 包含 Exception 事件数据的类 
 /// </summary> 
 public class ExceptionEventArgs : System.EventArgs 
 { 
  private System.Exception _Exception; 
  private ExceptionActions _ExceptionAction;

private DownLoadState _DownloadState;

public DownLoadState DownloadState 
  { 
   get 
   { 
    return _DownloadState; 
   } 
  }

public Exception Exception 
  { 
   get 
   { 
    return _Exception; 
   } 
  }

public ExceptionActions ExceptionAction 
  { 
   get 
   { 
    return _ExceptionAction; 
   } 
   set 
   { 
    _ExceptionAction = value; 
   } 
  }

internal ExceptionEventArgs(System.Exception e, DownLoadState DownloadState) 
  { 
   this._Exception = e; 
   this._DownloadState = DownloadState; 
  } 
 }

/// <summary> 
 /// 包含 DownLoad 事件数据的类 
 /// </summary> 
 public class DownLoadEventArgs : System.EventArgs 
 { 
  private DownLoadState _DownloadState;

public DownLoadState DownloadState 
  { 
   get 
   { 
    return _DownloadState; 
   } 
  }

public DownLoadEventArgs(DownLoadState DownloadState) 
  { 
   this._DownloadState = DownloadState; 
  }

}

public class ThreadProcessEventArgs : System.EventArgs 
 { 
  private Thread _thread;

public Thread thread 
  { 
   get 
   { 
    return this._thread; 
   } 
  }

public ThreadProcessEventArgs(Thread thread) 
  { 
   this._thread = thread; 
  }

}

/// <summary> 
 /// 支持断点续传多线程下载的类 
 /// </summary> 
 public class HttpWebClient 
 { 
  private static object _SyncLockObject = new object();

public delegate void DataReceiveEventHandler(HttpWebClient Sender, DownLoadEventArgs e);

public event DataReceiveEventHandler DataReceive; //接收字节数据事件

public delegate void ExceptionEventHandler(HttpWebClient Sender, ExceptionEventArgs e);

public event ExceptionEventHandler ExceptionOccurrs; //发生异常事件

public delegate void ThreadProcessEventHandler(HttpWebClient Sender, ThreadProcessEventArgs e);

public event ThreadProcessEventHandler ThreadProcessEnd; //发生多线程处理完毕事件

private int _FileLength; //下载文件的总大小

public int FileLength 
  { 
   get 
   { 
    return _FileLength; 
   } 
  }

/// <summary> 
  /// 分块下载文件 
  /// </summary> 
  /// <param name="Address">URL 地址</param> 
  /// <param name="FileName">保存到本地的路径文件名</param> 
  /// <param name="ChunksCount">块数,线程数</param> 
  public void DownloadFile(string Address, string FileName, int ChunksCount) 
  { 
   int p = 0; // position 
   int s = 0; // chunk size 
   string a = null; 
   HttpWebRequest hwrq; 
   HttpWebResponse hwrp = null; 
   try 
   { 
    hwrq = (HttpWebRequest) WebRequest.Create(this.GetUri(Address)); 
    hwrp = (HttpWebResponse) hwrq.GetResponse(); 
    long L = hwrp.ContentLength;

hwrq.Credentials = this.m_credentials;

L = ((L == -1) || (L > 0x7fffffff)) ? ((long) 0x7fffffff) : L; //Int32.MaxValue 该常数的值为 2,147,483,647; 即十六进制的 0x7FFFFFFF

int l = (int) L;

this._FileLength = l;

//    在本地预定空间(竟然在多线程下不用先预定空间) 
    //    FileStream sw = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); 
    //    sw.Write(new byte[l], 0, l); 
    //    sw.Close(); 
    //    sw = null;

bool b = (hwrp.Headers["Accept-Ranges"] != null & hwrp.Headers["Accept-Ranges"] == "bytes"); 
    a = hwrp.Headers["Content-Disposition"]; //attachment 
    if (a != null) 
    { 
     a = a.Substring(a.LastIndexOf("filename=") + 9); 
    } 
    else 
    { 
     a = FileName; 
    }

int ss = s; 
    if (b) 
    { 
     s = l / ChunksCount; 
     if (s < 2 * 64 * 1024) //块大小至少为 128 K 字节 
     { 
      s = 2 * 64 * 1024; 
     } 
     ss = s; 
     int i = 0; 
     while (l > s) 
     { 
      l -= s; 
      if (l < s) 
      { 
       s += l; 
      } 
      if (i++ > 0) 
      { 
      
DownLoadState x = new DownLoadState(Address,
hwrp.ResponseUri.AbsolutePath, FileName, a, p, s, new
ThreadCallbackHandler(this.DownloadFileChunk)); 
       //       单线程下载 
       //       x.StartDownloadFileChunk();

x.httpWebClient = this; 
       //多线程下载 
       Thread t = new Thread(new ThreadStart(x.StartDownloadFileChunk)); 
       //this.OnThreadProcess(t); 
       t.Start();


      p += s; 
     } 
     s = ss; 
     byte[] buffer = this.ResponseAsBytes(Address, hwrp, s, FileName); 
     this.OnThreadProcess(Thread.CurrentThread);

//    lock (_SyncLockObject) 
     //    { 
     //     this._Bytes += buffer.Length; 
     //    } 
    } 
   } 
   catch (Exception e) 
   { 
    ExceptionActions ea = ExceptionActions.Throw; 
    if (this.ExceptionOccurrs != null) 
    { 
     DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p, s); 
     ExceptionEventArgs eea = new ExceptionEventArgs(e, x); 
     ExceptionOccurrs(this, eea); 
     ea = eea.ExceptionAction; 
    }

if (ea == ExceptionActions.Throw) 
    { 
     if (!(e is WebException) && !(e is SecurityException)) 
     { 
      throw new WebException("net_webclient", e); 
     } 
     throw; 
    } 
   }

}

internal void OnThreadProcess(Thread t) 
  { 
   if (ThreadProcessEnd != null) 
   { 
    ThreadProcessEventArgs tpea = new ThreadProcessEventArgs(t); 
    ThreadProcessEnd(this, tpea); 
   } 
  }

/// <summary> 
  /// 下载一个文件块,利用该方法可自行实现多线程断点续传 
  /// </summary> 
  /// <param name="Address">URL 地址</param> 
  /// <param name="FileName">保存到本地的路径文件名</param> 
  /// <param name="Length">块大小</param> 
  public void DownloadFileChunk(string Address, string FileName, int FromPosition, int Length) 
  { 
   HttpWebResponse hwrp = null; 
   string a = null; 
   try 
   { 
    //this._FileName = FileName; 
    HttpWebRequest hwrq = (HttpWebRequest) WebRequest.Create(this.GetUri(Address)); 
    //hwrq.Credentials = this.m_credentials; 
    hwrq.AddRange(FromPosition); 
    hwrp = (HttpWebResponse) hwrq.GetResponse(); 
    a = hwrp.Headers["Content-Disposition"]; //attachment 
    if (a != null) 
    { 
     a = a.Substring(a.LastIndexOf("filename=") + 9); 
    } 
    else 
    { 
     a = FileName; 
    }

byte[] buffer = this.ResponseAsBytes(Address, hwrp, Length, FileName); 
    //   lock (_SyncLockObject) 
    //   { 
    //    this._Bytes += buffer.Length; 
    //   } 
   } 
   catch (Exception e) 
   { 
    ExceptionActions ea = ExceptionActions.Throw; 
    if (this.ExceptionOccurrs != null) 
    { 
     DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, FromPosition, Length); 
     ExceptionEventArgs eea = new ExceptionEventArgs(e, x); 
     ExceptionOccurrs(this, eea); 
     ea = eea.ExceptionAction; 
    }

if (ea == ExceptionActions.Throw) 
    { 
     if (!(e is WebException) && !(e is SecurityException)) 
     { 
      throw new WebException("net_webclient", e); 
     } 
     throw; 
    } 
   } 
  }

internal byte[] ResponseAsBytes(string RequestURL, WebResponse Response, long Length, string FileName) 
  { 
   string a = null; //AttachmentName 
   int P = 0; //整个文件的位置指针 
   int num2 = 0; 
   try 
   { 
    a = Response.Headers["Content-Disposition"]; //attachment 
    if (a != null) 
    { 
     a = a.Substring(a.LastIndexOf("filename=") + 9); 
    }

long num1 = Length; //Response.ContentLength; 
    bool flag1 = false; 
    if (num1 == -1) 
    { 
     flag1 = true; 
     num1 = 0x10000; //64k 
    } 
    byte[] buffer1 = new byte[(int) num1];

int p = 0; //本块的位置指针

string s = Response.Headers["Content-Range"]; 
    if (s != null) 
    { 
     s = s.Replace("bytes ", ""); 
     s = s.Substring(0, s.IndexOf("-")); 
     P = Convert.ToInt32(s); 
    } 
    int num3 = 0;

Stream S = Response.GetResponseStream(); 
    do 
    { 
     num2 = S.Read(buffer1, num3, ((int) num1) - num3);

num3 += num2; 
     if (flag1 && (num3 == num1)) 
     { 
      num1 += 0x10000; 
      byte[] buffer2 = new byte[(int) num1]; 
      Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3); 
      buffer1 = buffer2; 
     }

//    lock (_SyncLockObject) 
     //    { 
     //     this._bytes += num2; 
     //    } 
     if (num2 > 0) 
     { 
      if (this.DataReceive != null) 
      { 
       byte[] buffer = new byte[num2]; 
       Buffer.BlockCopy(buffer1, p, buffer, 0, buffer.Length); 
       DownLoadState dls = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2, buffer); 
       DownLoadEventArgs dlea = new DownLoadEventArgs(dls); 
       //触发事件 
       this.OnDataReceive(dlea); 
       //System.Threading.Thread.Sleep(100);


      p += num2; //本块的位置指针 
      P += num2; //整个文件的位置指针 
     } 
     else 
     { 
      break; 
     }


    while (num2 != 0);

S.Close(); 
    S = null; 
    if (flag1) 
    { 
     byte[] buffer3 = new byte[num3]; 
     Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3); 
     buffer1 = buffer3; 
    } 
    return buffer1; 
   } 
   catch (Exception e) 
   { 
    ExceptionActions ea = ExceptionActions.Throw; 
    if (this.ExceptionOccurrs != null) 
    { 
     DownLoadState x = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2); 
     ExceptionEventArgs eea = new ExceptionEventArgs(e, x); 
     ExceptionOccurrs(this, eea); 
     ea = eea.ExceptionAction; 
    }

if (ea == ExceptionActions.Throw) 
    { 
     if (!(e is WebException) && !(e is SecurityException)) 
     { 
      throw new WebException("net_webclient", e); 
     } 
     throw; 
    } 
    return null; 
   } 
  }

private void OnDataReceive(DownLoadEventArgs e) 
  { 
   //触发数据到达事件 
   DataReceive(this, e); 
  }

public byte[] UploadFile(string address, string fileName) 
  { 
   return this.UploadFile(address, "POST", fileName, "file"); 
  }

public string UploadFileEx(string address, string method, string fileName, string fieldName) 
  { 
   return Encoding.ASCII.GetString(UploadFile(address, method, fileName, fieldName)); 
  }

public byte[] UploadFile(string address, string method, string fileName, string fieldName) 
  { 
   byte[] buffer4; 
   FileStream stream1 = null; 
   try 
   { 
    fileName = Path.GetFullPath(fileName); 
    string text1 = "---------------------" + DateTime.Now.Ticks.ToString("x");

string text2 = "application/octet-stream";

stream1 = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
    WebRequest request1 = WebRequest.Create(this.GetUri(address)); 
    request1.Credentials = this.m_credentials; 
    request1.ContentType = "multipart/form-data; boundary=" + text1;

request1.Method = method; 
    string[] textArray1 = new
string[7] {"--", text1, "\r\nContent-Disposition: form-data; name=\"" +
fieldName + "\"; filename=\"", Path.GetFileName(fileName),
"\"\r\nContent-Type: ", text2, "\r\n\r\n"}; 
    string text3 = string.Concat(textArray1); 
    byte[] buffer1 = Encoding.UTF8.GetBytes(text3); 
    byte[] buffer2 = Encoding.ASCII.GetBytes("\r\n--" + text1 + "\r\n"); 
    long num1 = 0x7fffffffffffffff; 
    try 
    { 
     num1 = stream1.Length; 
     request1.ContentLength = (num1 + buffer1.Length) + buffer2.Length; 
    } 
    catch 
    { 
    } 
    byte[] buffer3 = new byte[Math.Min(0x2000, (int) num1)]; 
    using (Stream stream2 = request1.GetRequestStream()) 
    { 
     int num2; 
     stream2.Write(buffer1, 0, buffer1.Length); 
     do 
     { 
      num2 = stream1.Read(buffer3, 0, buffer3.Length); 
      if (num2 != 0) 
      { 
       stream2.Write(buffer3, 0, num2); 
      } 
     } 
     while (num2 != 0); 
     stream2.Write(buffer2, 0, buffer2.Length); 
    } 
    stream1.Close(); 
    stream1 = null; 
    WebResponse response1 = request1.GetResponse();

buffer4 = this.ResponseAsBytes(response1); 
   } 
   catch (Exception exception1) 
   { 
    if (stream1 != null) 
    { 
     stream1.Close(); 
     stream1 = null; 
    } 
    if (!(exception1 is WebException) && !(exception1 is SecurityException)) 
    { 
     //throw new WebException(SR.GetString("net_webclient"), exception1); 
     throw new WebException("net_webclient", exception1); 
    } 
    throw; 
   } 
   return buffer4; 
  }

private byte[] ResponseAsBytes(WebResponse response) 
  { 
   int num2; 
   long num1 = response.ContentLength; 
   bool flag1 = false; 
   if (num1 == -1) 
   { 
    flag1 = true; 
    num1 = 0x10000; 
   } 
   byte[] buffer1 = new byte[(int) num1]; 
   Stream stream1 = response.GetResponseStream(); 
   int num3 = 0; 
   do 
   { 
    num2 = stream1.Read(buffer1, num3, ((int) num1) - num3); 
    num3 += num2; 
    if (flag1 && (num3 == num1)) 
    { 
     num1 += 0x10000; 
     byte[] buffer2 = new byte[(int) num1]; 
     Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3); 
     buffer1 = buffer2; 
    } 
   } 
   while (num2 != 0); 
   stream1.Close(); 
   if (flag1) 
   { 
    byte[] buffer3 = new byte[num3]; 
    Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3); 
    buffer1 = buffer3; 
   } 
   return buffer1; 
  }

private NameValueCollection m_requestParameters; 
  private Uri m_baseAddress; 
  private ICredentials m_credentials = CredentialCache.DefaultCredentials;

public ICredentials Credentials 
  { 
   get 
   { 
    return this.m_credentials; 
   } 
   set 
   { 
    this.m_credentials = value; 
   } 
  }

public NameValueCollection QueryString 
  { 
   get 
   { 
    if (this.m_requestParameters == null) 
    { 
     this.m_requestParameters = new NameValueCollection(); 
    } 
    return this.m_requestParameters; 
   } 
   set 
   { 
    this.m_requestParameters = value; 
   } 
  }

public string BaseAddress 
  { 
   get 
   { 
    if (this.m_baseAddress != null) 
    { 
     return this.m_baseAddress.ToString(); 
    } 
    return string.Empty; 
   } 
   set 
   { 
    if ((value == null) || (value.Length == 0)) 
    { 
     this.m_baseAddress = null; 
    } 
    else 
    { 
     try 
     { 
      this.m_baseAddress = new Uri(value); 
     } 
     catch (Exception exception1) 
     { 
      throw new ArgumentException("value", exception1); 
     } 
    } 
   } 
  }

private Uri GetUri(string path) 
  { 
   Uri uri1; 
   try 
   { 
    if (this.m_baseAddress != null) 
    { 
     uri1 = new Uri(this.m_baseAddress, path); 
    } 
    else 
    { 
     uri1 = new Uri(path); 
    } 
    if (this.m_requestParameters == null) 
    { 
     return uri1; 
    } 
    StringBuilder builder1 = new StringBuilder(); 
    string text1 = string.Empty; 
    for (int num1 = 0; num1 < this.m_requestParameters.Count; num1++) 
    { 
     builder1.Append(text1 + this.m_requestParameters.AllKeys[num1] + "=" + this.m_requestParameters[num1]); 
     text1 = "&"; 
    } 
    UriBuilder builder2 = new UriBuilder(uri1); 
    builder2.Query = builder1.ToString(); 
    uri1 = builder2.Uri; 
   } 
   catch (UriFormatException) 
   { 
    uri1 = new Uri(Path.GetFullPath(path)); 
   } 
   return uri1; 
  }

}

}

/// <summary> 
/// 测试类 
/// </summary> 
class AppTest 

 int _k = 0; 
 int _K = 0;

static void Main() 
 { 
  AppTest a = new AppTest(); 
  Microshaoft.Utils.HttpWebClient x = new Microshaoft.Utils.HttpWebClient();

a._K = 10;

//订阅 DataReceive 事件 
  x.DataReceive += new Microshaoft.Utils.HttpWebClient.DataReceiveEventHandler(a.x_DataReceive); 
  //订阅 ExceptionOccurrs 事件 
  x.ExceptionOccurrs += new Microshaoft.Utils.HttpWebClient.ExceptionEventHandler(a.x_ExceptionOccurrs);

x.ThreadProcessEnd += new Microshaoft.Utils.HttpWebClient.ThreadProcessEventHandler(a.x_ThreadProcessEnd); 
  string F = "http://localhost/download/phpMyAdmin-2.6.1-pl2.zip "; 
  a._F = F; 
  F = "http://localhost/download/jdk-1_5_0_01-windows-i586-p.aa.exe "; 
  //F = "http://localhost/download/ReSharper1.5.exe ";

//F = "http://localhost/mywebapplications/WebApplication7/WebForm1.aspx "; 
  //F = "http://localhost:1080/test/download.jsp ";

//F = "http://localhost/download/Webcast20050125_PPT.zip "; 
  //F = "http://www.morequick.com/greenbrowsergb.zip "; 
  //F = "http://localhost/download/test_local.rar "; 
  string f = F.Substring(F.LastIndexOf("/") + 1);

//(new System.Threading.Thread(new System.Threading.ThreadStart(new
ThreadProcessState(F, @"E:\temp\" + f, 10,
x).StartThreadProcess))).Start();

x.DownloadFile(F, @"E:\temp\temp\" + f, a._K); 
  //  x.DownloadFileChunk(F, @"E:\temp\" + f,15,34556);

System.Console.ReadLine(); 
  //  string uploadfile = "e:\\test_local.rar"; 
  //  string str = x.UploadFileEx("http://localhost/phpmyadmin/uploadaction.php ", "POST", uploadfile, "file1"); 
  //  System.Console.WriteLine(str); 
  //  System.Console.ReadLine(); 
 }

string bs = ""; //用于记录上次的位数 
 bool b = false; 
 private int i = 0; 
 private static object _SyncLockObject = new object(); 
 string _F; 
 string _f;

private void x_DataReceive(Microshaoft.Utils.HttpWebClient Sender, Microshaoft.Utils.DownLoadEventArgs e) 
 { 
  if (!this.b) 
  { 
   lock (_SyncLockObject) 
   { 
    if (!this.b) 
    { 
     System.Console.Write(System.DateTime.Now.ToString() + " 已接收数据:           "); 
     //System.Console.Write( System.DateTime.Now.ToString() + " 已接收数据:           "); 
     this.b = true; 
    } 
   } 
  } 
  string f = e.DownloadState.FileName; 
  if (e.DownloadState.AttachmentName != null) 
   f = System.IO.Path.GetDirectoryName(f) + @"\" + e.DownloadState.AttachmentName;

this._f = f;

using (System.IO.FileStream sw = new System.IO.FileStream(f,
System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite,
System.IO.FileShare.ReadWrite)) 
  { 
   sw.Position = e.DownloadState.Position; 
   sw.Write(e.DownloadState.Data, 0, e.DownloadState.Data.Length); 
   sw.Close(); 
  } 
  string s = System.DateTime.Now.ToString(); 
  lock (_SyncLockObject) 
  { 
   this.i += e.DownloadState.Data.Length; 
   System.Console.Write(bs + "\b\b\b\b\b\b\b\b\b\b" + i + " / " + Sender.FileLength + " 字节数据 " + s); 
   //System.Console.Write(bs + i + " 字节数据 " + s); 
   this.bs = new string('\b', Digits(i) + 3 + Digits(Sender.FileLength) + s.Length); 
  } 
 }

int Digits(int n) //数字所占位数 
 { 
  n = System.Math.Abs(n); 
  n = n / 10; 
  int i = 1; 
  while (n > 0) 
  { 
   n = n / 10; 
   i++; 
  } 
  return i; 
 }

private void x_ExceptionOccurrs(Microshaoft.Utils.HttpWebClient Sender, Microshaoft.Utils.ExceptionEventArgs e) 
 { 
  System.Console.WriteLine(e.Exception.Message); 
  //发生异常重新下载相当于断点续传,你可以自己自行选择处理方式 
  Microshaoft.Utils.HttpWebClient x = new Microshaoft.Utils.HttpWebClient(); 
  x.DownloadFileChunk(this._F, this._f, e.DownloadState.Position, e.DownloadState.Length); 
  e.ExceptionAction = Microshaoft.Utils.ExceptionActions.Ignore; 
 }

private void x_ThreadProcessEnd(Microshaoft.Utils.HttpWebClient Sender, Microshaoft.Utils.ThreadProcessEventArgs e) 
 { 
  //if (e.thread.ThreadState == System.Threading.ThreadState.Stopped) 
  if (this._k ++ == this._K - 1) 
   System.Console.WriteLine("\nend"); 
 } 
}

C# 断点续传原理与实现的更多相关文章

  1. Android开发——断点续传原理以及实现

    0.  前言 在Android开发中,断点续传听起来挺容易,在下载一个文件时点击暂停任务暂停,点击开始会继续下载文件.但是真正实现起来知识点还是蛮多的,因此今天有时间实现了一下,并进行记录.本文原创, ...

  2. 文件断点续传原理与实现—— ESFramework 通信框架4.0 进阶(12)

    在ESFramework通信框架 4.0 快速上手(13) -- 文件传送,如此简单一文的详细介绍和ESFramework通信框架 4.0 快速上手(14) -- 聊天系统Demo,增加文件传送功能( ...

  3. http断点续传原理:http头 Range、Content-Range

    所谓断点续传,也就是要从文件已经下载的地方开始继续下载.在以前版本的 HTTP 协议是不支持断点的,HTTP/1.1 开始就支持了.一般断点下载时才用到 Range 和 Content-Range 实 ...

  4. http断点续传原理

    断点续传一是断点,一续传. 断点是在下载时,将下载文件分多片,同时进行多片一起下载,如果任务被暂停,暂停的位置就是断点. 续传就是未完成的下载再次开始时,会从上次的断点继续传送. 在下载(或上传)过程 ...

  5. Http头 Range、Content-Range(http断点续传原理)

    HTTP头中一般断点下载时才用到Range和Content-Range实体头,Range用户请求头中,指定第一个字节的位置和最后一个字节的位置,如(Range:200-300)Content-Rang ...

  6. QT断点续传(原理:需要在HTTP请求的header中添加Rang节,告诉服务器从文件的那个位置开始传输.格式为bytes 开始传输的位置)

    //功能:    根据一个URL地址将数据保存到指定路径下,支持断点续传//参数:    url            --需要访问的URL地址//         SavePath       -- ...

  7. PHP 实现断点续传的原理和方法

    PHP 实现断点续传的原理和方法 0. http协议从1.1开始支持静态获取文件的部分内容,为多线程下载和断点续传提供了技术支持.它通过在Header里两个参数实现的,客户端发请求时对应的是Accep ...

  8. http断点续传的原理

    ——————————————先讲原理,如下:—————————————————— 举一个详细的例子: 一般场景,要访问的域名:www.jizhuomi.com/android,文件名为down.zip ...

  9. HTML5实现文件断点续传

    HTML5的FILE api,有一个slice方法,可以将BLOB对象进行分割.前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段 ...

随机推荐

  1. android加固系列—6.仿爱加密等第三方加固平台之动态加载dex防止apk被反编译

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5402599.html ] 此方案的目的是隐藏源码防止直接性的反编译查看源码,原理是加密编译好的 ...

  2. 【C语言】C语言数据类型

    目录: [数据类型图] [基本数据类型]   · 整型   · 实型   · 字符型   · 布尔类型 1.数据类型图 2.基本数据类型 · 整型 用于准确表示整数,根据表示范围的不同分为三种:短整型 ...

  3. block 页面传值小结

    我以自己项目中的一个模块为例,首先有两个页面,第一个页面为显示城市页面,第二个页面为选择要使用block传的值(城市名). 第一个页面中的显示控件: //自定义左部定位视图 self.locView ...

  4. 自定义Dialog宽度占满屏幕

    一.自定义Dialog继承Dialog public class MyDialog extends Dialog { 二.为Dialog设置样式 在style中建立新样式继承 @android:sty ...

  5. [读书笔记] Head First 设计模式

    OO基础 抽象 封装 多态 继承 OO原则 原则 描述 封装变化 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混合在一起. 把会变化的部分取出来并“封装”起来,好让其他部分不 ...

  6. android Gui系统之SurfaceFlinger(4)---Vsync(1)

    8.Vsync 8.1概论 VSYNC(Vertical Synchronization)是一个相当古老的概念,对于游戏玩家,它有一个更加大名鼎鼎的中文名字—-垂直同步. “垂直同步(vsync)”指 ...

  7. Newtonsoft.Json 把对象转换成json字符串

    var resultJson = new { records = rowCount, page = pageindex, //总页数=(总页数+页大小-1)/页大小 total = (rowCount ...

  8. PHP isset() 检测变量是否设置

    isset() 用于检测变量是否设置. isset() PHP isset() 用于检测一个或多个变量是否设置,如果被检测的变量存在则返回 TRUE,否则返回 FALSE. 语法: 1 bool is ...

  9. 利用PHPMailer 来完成PHP的邮件发送

    翻起之前的代码看了一下,还是发表到这里,以后容易查找. 以下的两个文件在这里下载 http://download.csdn.net/detail/u013085496/9673828 也可以直接上gi ...

  10. 使用Web.Config Transformation配置灵活的配置文件

    发布Asp.net程序的时候,开发环境和发布环境的Web.Config往往不同,比如connectionstring等.如果常常有发布的需求,就需要常常修改web.config文件,这往往是一件非常麻 ...