• [c#] 断点续传下载文件[带进度条类似迅雷]


           在.net里关于用Http下载文件,有HttpWebRequest实在是简单。通常用这个组建可以轻松为自己量身定做一个类似于迅雷的下载软件,只要你舍得花这个时间。当然,你还可以从socket方面入手,因为那个比用HTTP实现更底层,操作起来更细腻。但我们现在要说的与那无关,迅雷电驴云云,这些下载软件实在是太方便了,以至于我们看起来毫无写这方面软件的必要了。但是,这方面的资料还是必须掌握一点,在很多方面都会用得着。

           当然还没说到正题,先说下实现步骤:1.监视剪切板,判断是否含有可以供下载的链接。2.建立下载任务,实时记录下载进度。 3.进度条显示进度。

    先说下迅雷的下载格式:

    thunder://QUFodHRwOi8veGlhemFpLnpvbC5jb20uY24vZG93bi5waHA/c29mdGlkPTExNDkyOSZzdWJjYXRpZD0zNDUmc2l0ZT0xMFpa

    thunder://后面一连串的字符串是base64加密而成,因此,我们在下载迅雷协议格式的文件时,必须先解码成Unicode文本。

    AAhttp://xiazai.zol.com.cn/down.php?softid=114929&subcatid=345&site=10ZZ

    去掉 “AA” “ZZ”就是地址了。


    using System.IO;//引入输入输出功能
    using System.Net;//网络请求
    using System.Text.RegularExpressions;//用于正则表达式字符串处理
    using System.Runtime.InteropServices;//引入WinAPI功能函数
    using System.Threading;//处理线程

    准备一下功能函数
    1.加载已经存在的INI配置文件

    View Code
    /// <summary>
            /// 为INI文件中指定的节点取得字符串
            /// </summary>
            /// <param name="lpAppName">欲在其中查找关键字的节点名称</param>
            /// <param name="lpKeyName">欲获取的项名</param>
            /// <param name="lpDefault">指定的项没有找到时返回的默认值</param>
            /// <param name="lpReturnedString">指定一个字串缓冲区,长度至少为nSize</param>
            /// <param name="nSize">指定装载到lpReturnedString缓冲区的最大字符数量</param>
            /// <param name="lpFileName">INI文件名</param>
            /// <returns>复制到lpReturnedString缓冲区的字节数量,其中不包括那些NULL中止字符</returns>
            [DllImport("kernel32")]
            public static extern int GetPrivateProfileString(
                string lpAppName,
                string lpKeyName,
                string lpDefault,
                StringBuilder lpReturnedString,
                int nSize,
                string lpFileName);
            #endregion
    View Code
    /// <summary>
            /// 从INI文件中读取指定节点的内容
            /// </summary>
            /// <param name="section">INI节点</param>
            /// <param name="key">节点下的项</param>
            /// <param name="def">没有找到内容时返回的默认值</param>
            /// <param name="def">要读取的INI文件</param>
            /// <returns>读取的节点内容</returns>
            public static string ReadString(string section, string key, string def, string fileName)
            {
                StringBuilder temp = new StringBuilder(1024);
                GetPrivateProfileString(section, key, def, temp, 1024, fileName);
                return temp.ToString();
            }

    2.写入INI文件

    View Code
      /// <summary>
            /// 修改INI文件中内容
            /// </summary>
            /// <param name="lpApplicationName">欲在其中写入的节点名称</param>
            /// <param name="lpKeyName">欲设置的项名</param>
            /// <param name="lpString">要写入的新字符串</param>
            /// <param name="lpFileName">INI文件名</param>
            /// <returns>非零表示成功,零表示失败</returns>
            [DllImport("kernel32")]
            public static extern int WritePrivateProfileString(
                string lpApplicationName,
                string lpKeyName,
                string lpString,
                string lpFileName);
            #endregion

    好了,准备工作做完了。先建立几个全局变量。

           static string FileName = "";//记录要下载的文件名
           static long FileLength = 0; //记录文件大小
           static  int CompletedLength = 0;//记录已完成的大小

    下面完成下载功能,注释里面都有。最适合初学的人看了。^!^

    View Code
    /// <summary>
            /// 以断点续传方式下载文件
            /// </summary>
            /// <param name="strFileName">下载文件的保存路径</param>
            /// <param name="strUrl">文件下载地址</param>
            public void DownloadFile(string strFileName, string strUrl)
            {
                //打开上次下载的文件或新建文件
               int CompletedLength = 0;//记录已完成的大小
              
                FileStream FStream;
                if (File.Exists(strFileName))
                {
                    FStream = File.OpenWrite(strFileName);
                    sPosstion = FStream.Length;
                    FStream.Seek(sPosstion, SeekOrigin.Current);//移动文件流中的当前指针
                }
                else
                {
                    FStream = new FileStream(strFileName, FileMode.Create);
                    sPosstion = 0;
                }
                //打开网络连接
                try
                {
                    HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(strUrl);
                    if (CompletedLength > 0)
                        myRequest.AddRange((int)CompletedLength);//设置Range值
                    //向服务器请求,获得服务器的回应数据流
                    HttpWebResponse webResponse = (HttpWebResponse)myRequest.GetResponse();
                    FileLength = webResponse.ContentLength;//文件大小
                    Stream myStream = webResponse.GetResponseStream();
                    byte[] btContent = new byte[1024];
                   if(count<=0) count += sPosstion;
    
                    while ((CompletedLength = myStream.Read(btContent, 0, 1024)) > 0)
                    {
                        FStream.Write(btContent, 0, CompletedLength);
                        count += CompletedLength;
                    }
                    FStream.Close();
                    myStream.Close();
                    MessageBox.Show("文件下载完成!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch
                {
                    FStream.Close();
                }
            }

    这就是最终的效果了。当然迅雷可不是这么简单,要达到迅雷那样的效果火候肯定是不够的。这里面有很多新手值得去学习的地方,这个代码不是我的原创,是我从网上下载后修改完成的。因为我觉得里面确实有很多可以学习鉴戒的地方,因此一时手痒供上给大家了。具体的源码在评论处会补上,欢迎大家下载~!

    教程每天都更新,欢迎大家继续关注!



    ///******************************************************
    ///本文作者:凌晨的搜索者
    ///博客地址:http://www.cnblogs.com/uu102
    ///本文属于原创,如果有您需要的内容想要转载,请保留此段签名注释,否则作者将保留追究法律责任的权利。
    ///******************************************************
  • 相关阅读:
    MongoDB+模板引擎 项目实例-学生档案管理
    MongoDB 增删改查命令速查
    MongoDB 数据库概述及环境搭建
    Flutter 升级
    TypeScript 快速上手及学习笔记
    Android ContentProvider 启动分析
    HTTP 报文格式简介
    深入浅出 HTTPS (详解版)
    从你输入网址,到看到网页——详解中间发生的过程
    TCP 三次握手和四次挥手图解(有限状态机)
  • 原文地址:https://www.cnblogs.com/uu102/p/2720572.html
Copyright © 2020-2023  润新知