`

多线程与断点续传

 
阅读更多
引自
http://www.devdiv.com/thread-20925-1-1.html





本帖最后由 wt0731 于 2010-1-15 09:01 编辑


起因:公司有个项目用到了断点续传,之前开发了一套但是由于现场环境的问题导致不能用(原理是用aspnet_isapi.dll来响应PUT和POST请求),后来考虑换个模式,当中要感谢帮助过我的人(pkwsh、egmkang等)
1、断点续传的原理(来自网络)
在了解HTTP断点续传的原理之前,先来说说HTTP协议,HTTP协议是一种基于tcp的简单协议,分为请求和回复两种。
请求协议是由客户机(浏览器)向服务器(WEB SERVER)提交请求时发送报文的协议。回复协议是由服务器(web ser
ver),向客户机(浏览器)回复报文时的协议。请求和回复协议都由头和体组成。头和体之间以一行空行为分隔。
以下是一个请求报文与相应的回复报文的例子:
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协议中,可以在请求报文头中加入Rang
e段,来表示客户机希望从何处继续下载。
比如说从第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类的三个属性表示。

2、网上的可以跑的示例
代码实现
了解了.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());
                     }
3、服务端的配置

   配置一个站点,并给Asp.Net和NetWorkService用读取并运行权限
4、完善(加上简单逻辑、多线程)
#region 作者:wt0731, 2010-01-02
/*
* 版本 :1.0
* 维护者:
* 最近维护日期:
*
*/
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace DownloadFile
{
    public partial class FormDownLoad : Form
    {
        private Thread threadDownload = null;
        private Thread threadUpload = null;
        /// <summary>
        /// 下载路径
        /// </summary>
        private string DownloadPath = "http://192.168.100.46/HttpHandle/2.rar";//根据实际需要修改

        /// <summary>
        /// 本地存储路径
        /// </summary>
        private string localSourceFile = string.Empty;
        /// <summary>
        /// 暂停
        /// </summary>
        private bool dlThreadContinue = false;
        public FormDownLoad()
        {
            InitializeComponent();
            this.btnStop.Enabled = false;
        }

        private void btnDownLoad_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            this.btnDownLoad.Enabled = false;
            this.dlThreadContinue = true;
            this.btnStop.Enabled = true;
            localSourceFile = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\" + this.txtName.Text.ToString(); //根据实际情况设置
            DownloadPath = this.txtUrl.Text.ToString(); //根据实际情况设置
            threadDownload = new Thread(new ThreadStart(DownloadThread));
            threadDownload.Start();           
        }

        /// <summary>
        /// 下载线程的入口函数
        /// </summary>
        void DownloadThread()
        {         
             DownloadFile(this.DownloadPath,this.localSourceFile);        
        }

         /// <summary>
        /// 下载文件,无压缩传输
        /// </summary>
        /// <param name="serverUrl">服务端处理Http请求的地址</param>param>
        /// <param name="fileName">本地存储的文件名</param>
        private void DownloadFile(string serverUrl, string fileName)    
        {
            //打开上次下载的文件或新建文件
            long lStartPos = 0;
            System.IO.FileStream fs;
            if (System.IO.File.Exists(fileName))
            {
                fs = System.IO.File.OpenWrite(fileName);
                lStartPos = fs.Length;
                fs.Seek(lStartPos, System.IO.SeekOrigin.Current); //移动文件流中的当前指针
            }
            else
            {
                fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
                lStartPos = 0;
            }
            //打开网络连接
            try
            {
                System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(serverUrl);
                request.KeepAlive = true;
                if (lStartPos > 0)
                    request.AddRange((int)lStartPos); //设置Range值 
                System.Text.Encoding utf8 = System.Text.Encoding.Default;
                //向服务器请求,获得服务器回应数据流
                System.IO.Stream ns = request.GetResponse().GetResponseStream();

                byte[] nbytes = new byte[1024];
                int nReadSize = 0;
                nReadSize = ns.Read(nbytes, 0, 1024);
                while (nReadSize > 0 && dlThreadContinue)
                {
                    fs.Write(nbytes, 0, nReadSize);
                    nReadSize = ns.Read(nbytes, 0, 1024);
                }
                //fs.Flush();
                fs.Close();
                ns.Close();
                Cursor.Current = Cursors.Default;
                MessageBox.Show("下载完成", "系统提示");
            }
            catch (Exception ex)
            {
                Cursor.Current = Cursors.Default;
                fs.Close();
                MessageBox.Show("下载过程中出现错误:" + ex.ToString(), "系统提示");
            }
        }
        private void menuItem1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (this.btnStop.Text == "暂停")
            {
                this.dlThreadContinue = false;
                Cursor.Current = Cursors.Default;
                this.btnDownLoad.Enabled = true;
                this.btnStop.Enabled = false;
            }                     
        }      
    }
}
复制代码
扩展资料:
HttpWebRequest&HttpWebResponse Headers
介绍
这里简要介绍如何使用HttpWebRequest&HttpWebResponse两个对象与HTTP服务器进行直接交互的过程.HttpWebRequest类对WebRequest中定义的属性和方法提供支持,在使用HttpWebRequest对象向HTTP服务器发起请求时请不要使用HttpWebRequest对象的构造函数,而应该使用WebRequest.Create()方法来初始化新的HttpWebRequest对象.如果统一资源标识符方案是"http://"或"https://"时,Create()则返回HttpWebResponse对象.
代码
首先,我们需要创建一个新的HttpWebRequest对象,代码如下:
HttpWebRequest myrequest = (HttpWebRequest)WebRequest.Create(new Uri("urlstring"));
注意:上文中已经提到过不要使用HttpWebRequest的构造函数来创建对象;使用WebRequest.Create()方法初始化HttpWebRequest对象时应该对其进行类型转换.
接下来可以对新初始化的对象进行简单操作,比如可以设置它的标头属性,
下表列出了由属性或方法设置或由系统设置的标头:
________________________________________

标头         设置方法
Accept         由Accept属性设置
Connection         由Connection属性和KeepAlive属性设置
Content-Length         由ContentLength属性设置
Content-Type         由ContentType属性设置
Expect         由Expect属性设置
Date         由系统设置为当前日期
Host         由系统设置为当前主机信息
If-Modified-Since         由IfModifiedSince属性设置
Range         由Range属性设置
Transfer-Encoding         由TransferEncoding属性设置
Referer         由Referer属性设置
User-Agent         由UserAgent属性设置
________________________________________
注意:HttpWebRequest自动注册.使用以"http://"或"https://"开头的URL之前,不需要调用RegisterPrefix方法来注册
源码下载:
分享到:
评论

相关推荐

    Http多线程与断点续传的Dll+源码

    本文将深入解析标题为“Http多线程与断点续传的Dll+源码”的技术内容,以及如何利用提供的Dll库和源码实现这些功能。 首先,我们来看“Http多线程”这一概念。HTTP(超文本传输协议)是我们日常浏览网页、下载文件...

    VC HTTP多线程与断点续传下载示例

    本文将深入探讨在Visual C++(简称VC)环境下实现HTTP协议的多线程下载与断点续传技术,这对于提升大文件下载效率和用户体验至关重要。 HTTP(超文本传输协议)是互联网上应用最广泛的数据通信协议之一,用于从Web...

    java实现FTP多线程断点续传

    ### Java实现FTP多线程断点续传:深入解析与技术要点 在现代软件开发中,数据传输是一项基本且关键的任务,特别是在处理大文件时,断点续传功能显得尤为重要。断点续传允许在网络连接中断后恢复传输,避免了重新...

    python多线程,断点续传下载程序

    python多线程,断点续传下载程序,功能比较简单,可以进行二次开发。实现更好用的 功能。

    多线程+断点续传 完整资源!

    在IT行业中,多线程和断点续传是两种非常重要的技术,特别是在文件下载领域。这两项技术的应用极大地提高了效率和用户体验。以下是对这两个概念的详细解释和它们如何结合使用的阐述。 多线程(Multi-threading)是...

    多线程下载支持断点续传

    在IT领域,多线程下载和断点续传是提高下载效率和用户体验的重要技术。这里,我们将深入探讨这两个概念,并结合使用HttpURLConnection实现的多线程下载工具进行讲解。 首先,多线程下载是一种利用网络资源的方式,...

    Android 多线程可断点续传上传文件至服务器Demo

    Android 多线程可断点续传上传文件至服务器Demo(Android端编辑器:Android Studio,服务器端编辑器:Eclipse,请注意手机默认下载目录必须要有t007.zip,服务器端必须有D:\temp\temp目录)

    多线程断点续传下载实现

    在Android开发中,多线程断点续传技术是一种提高下载效率并优化用户体验的重要方法。这一技术主要应用于大型文件的下载场景,如游戏、应用程序或高清视频等,它允许用户在下载过程中随时暂停,之后能从中断的地方...

    c/c++线程断点续传实现

    在C/C++编程中,实现线程断点续传是一项技术挑战,特别是在处理大文件下载时,这种功能显得尤为重要。断点续传允许程序在中断后从上次停止的地方继续下载,提高了用户体验并节省了网络资源。Cocos2dx是一个基于C++的...

    java ftp 多线程 断点续传等知识

    而"多线程"和"断点"这两个文件名可能是指相关示例代码或文档,可以进一步帮助你理解和实践Java FTP的多线程下载和断点续传。 在实际应用中,还需要考虑其他因素,如错误处理、网络状况的监控、文件完整性检查等。...

    c#多线程断点续传

    在提供的压缩包文件中,可能包含了一个名为“download”的示例项目,这可能是用于演示上述多线程断点续传功能的源代码。通过分析和运行这个项目,你可以更直观地理解这两种技术的结合应用。 总之,多线程和断点续传...

    android多线程断点续传

    在Android开发中,多线程断点续传是一项重要的技术,尤其在处理大文件下载时。这个技术的主要目的是提高下载效率并确保用户可以中断或恢复下载过程。以下将详细讲解多线程断点续传的概念、实现原理以及在Android中的...

    java断点续传,刚刚整理出来多线程处理

    然而,实现多线程断点续传需要解决几个问题: 1. **同步管理**:多个线程可能会同时访问同一个文件的部分,因此需要使用`synchronized`关键字或`Lock`对象来确保并发安全。 2. **断点信息共享**:每个线程需要知道...

    多线程断点续传

    在开源社区中,有许多工具和库实现了多线程断点续传功能,如迅雷、aria2等下载工具,它们提供了丰富的API和配置选项,方便开发者集成到自己的应用中。而博文链接中提到的"iteye"博客文章可能详细探讨了这一主题,...

    linux多线程下载断点续传

    在Linux系统中,多线程下载和断点续传是两个关键的技术,它们极大地提高了文件下载的效率和用户体验。本文将深入探讨这两个概念,并结合标签中的"Linux"、"HTTP"以及"FTP"来详细解释。 首先,让我们理解多线程下载...

    多线程断点续传demo

    04_手机端多线程断点续传下载可能是一个具体的实现示例,包含代码或者配置文件,展示了如何将多线程与断点续传功能整合到一个应用程序中。 在实现多线程断点续传时,开发者需要考虑以下几个关键点: 1. **文件分块...

    java FTP多线程 批量 断点续传

    Java FTP多线程批量断点续传是一种在Java编程中实现高效、稳定文件传输的方法,尤其适用于大文件的上传和下载。在这个过程中,我们利用FTP(File Transfer Protocol)协议,结合多线程技术和断点续传功能,可以显著...

    基于HTTP协议的多线程下载he断点续传的实现.

    基于HTTP协议的多线程下载he断点续传的实现.基于HTTP协议的多线程下载he断点续传的实现.基于HTTP协议的多线程下载he断点续传的实现.基于HTTP协议的多线程下载he断点续传的实现.基于HTTP协议的多线程下载he断点续传的...

    Android多线程断点续传下载

    在Android开发中,多线程断点续传下载是一项重要的技术,它允许用户在网络连接不稳定或者设备突然断电的情况下,能够从上次中断的地方继续下载,提高了用户体验。本项目提供的"MultiThreadDownload"是一个实现这一...

    点对点多线程断点续传的实现

    在点对点网络中实现多线程断点续传,主要涉及以下几个关键技术点: 1. **网络连接与通信协议**:P2P网络通常使用TCP或UDP协议进行通信。TCP保证了数据的可靠传输,适合断点续传,而UDP则提供了更高的传输速度,但...

Global site tag (gtag.js) - Google Analytics