zoukankan      html  css  js  c++  java
  • 转:Http下载文件类 支技断点续传功能

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Net;
    using System.Threading;
    
    namespace Print.DownloadFile
    {
        /// <summary>
        /// Http下载文件类
        /// 支技断点续传功能
        /// </summary>
        public class HttpDownloadFile
        {
            #region<事件>
            public delegate void DownloadIngHandler(object sender, DownloadIngEventArgs e);
            /// <summary>
            /// 每收到一个文件下载数据时触发
            /// </summary>
            public event DownloadIngHandler onDownloadIng;
            public delegate void DownloadEndHandler(object sender, DownloadendEventArgs e);
            /// <summary>
            /// 一个文件下载完成时触发
            /// </summary>
            public event DownloadEndHandler onDownloadEnd;
            public delegate void ValidateMD5ErrorHandler(object sender, ValidateMD5ErrorEventArgs e);
            /// <summary>
            /// 下载完后验证MD5错误
            /// </summary>
            public event ValidateMD5ErrorHandler onValidateMD5Error;
            public delegate void ExceptionHandler(object sender, ExceptionEventArgs e);
            /// <summary>
            /// 出现异常时触发
            /// </summary>
            public event ExceptionHandler onException;
            #endregion<End事件>
    
            #region<成员变量与属性>
            /// <summary>
            /// 文件的总大小
            /// </summary>
            private long m_totalFileSize = 0;
            /// <summary>
            /// 当前已经下载的大小
            /// </summary>
            private long m_currFileSize = 0;
            /// <summary>
            /// 是否为续传
            /// </summary>
            private bool m_isKeep = false;
            /// <summary>
            /// 是否停止下载
            /// </summary>
            private bool m_isStop = false;
            /// <summary>
            /// 文件名,不含路径
            /// </summary>
            private string m_fileName;
            /// <summary>
            /// 文件下载完成后用于验证文件完整性的MD5值
            /// </summary>
            private string m_Md5;
            /// <summary>
            /// 下载资源的URL
            /// </summary>
            private string m_url;
            /// <summary>
            /// 下载时需要登录的用户名
            /// </summary>
            private string m_username = string.Empty;
            /// <summary>
            /// 下载时需要登录的用户密码
            /// </summary>
            private string m_userpwd = string.Empty;
            /// <summary>
            /// 要保存文件的路路径
            /// </summary>
            private string m_savePath;
            /// <summary>
            /// 下载资源的代理服务器
            /// </summary>
            private string m_proxyip = string.Empty;
            /// <summary>
            /// 下载资源的代理端口
            /// </summary>
            private string m_proxyport = null;
            /// <summary>
            /// 当前下载文件的ID
            /// </summary>
            private string m_id = string.Empty;
            #endregion<end 成员变量与属性>
    
            #region<构造方法>
            /// <summary>
            /// Http文件下载对象
            /// </summary>
            /// <param name="url">下载的资源</param>
            /// <param name="username">用户名</param>
            /// <param name="userpwd">登录密码</param>
            /// <param name="savepath">本地保存的路径,包含文件名</param>
            /// <param name="proxyip">代理服务器</param>
            /// <param name="proxyport">代理端口</param>
            /// <param name="MD5">文件的MD5值,用于验证文件完整性</param>
            /// <param name="id">文件信息保存在数据中的ID</param>
            public HttpDownloadFile(string url, string username, string userpwd, string savepath,
                string proxyip, string proxyport, string MD5, string id)
                : this(url, username, userpwd, savepath, MD5, id)
            {
                m_proxyip = proxyip;
                m_proxyport = proxyport;
            }
            /// <summary>
            /// Http文件下载对象
            /// </summary>
            /// <param name="url">下载的资源</param>
            /// <param name="username">用户名</param>
            /// <param name="userpwd">登录密码</param>
            /// <param name="savepath">本地保存的路径,包含文件名</param>
            /// <param name="MD5">文件的MD5值,用于验证文件完整性</param>
            /// <param name="id">文件信息保存在数据中的ID</param>
            public HttpDownloadFile(string url, string username, string userpwd, string savepath, string MD5, string id)
                : this(url, savepath, MD5, id)
            {
                m_username = username;
                m_userpwd = userpwd;
            }
            /// <summary>
            /// Http文件下载对象
            /// </summary>
            /// <param name="url">下载的资源</param>
            /// <param name="savepath">本地保存的路径,包含文件名</param>
            /// <param name="MD5">文件的MD5值,用于验证文件完整性</param>
            /// <param name="id">文件信息保存在数据中的ID</param>
            public HttpDownloadFile(string url, string savepath, string MD5, string id)
            {
                m_url = url;
                m_savePath = savepath;
                m_Md5 = MD5;
                m_fileName = savepath.Substring(savepath.LastIndexOf('\') + 1);
                m_id = id;
            }
            #endregion<end构造方法>
    
            #region<方法>
            /// <summary>
            /// 开始下载文件
            /// </summary>
            public void StartDownloadFile()
            {
                m_isStop = false;
                string filePath = m_savePath.Substring(0, m_savePath.LastIndexOf('\'));
                if (!Directory.Exists(filePath))
    
                    Directory.CreateDirectory(filePath);
                FileStream fs = new FileStream(m_savePath, FileMode.OpenOrCreate);
                m_currFileSize = fs.Length;
                //如果是续传
                if (m_currFileSize > 0)
                {
                    this.m_isKeep = true;
                    fs.Seek(m_currFileSize, SeekOrigin.Current);
                }
                try
                {
                    Uri uri = new Uri(m_url);
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
                    if (!(string.IsNullOrEmpty(m_proxyip) || string.IsNullOrEmpty(m_proxyport)))
                    {
                        WebProxy myproxy = new WebProxy(m_proxyip, Convert.ToInt32(m_proxyport));
                        myproxy.BypassProxyOnLocal = true;
                        request.Proxy = myproxy;
                    }
                    NetworkCredential credentials = new NetworkCredential(m_username, m_userpwd);
                    request.Credentials = credentials;
                    //如果是续传,并且已经传完的文件大小0;
                    if (m_isKeep && m_currFileSize > 0)
                        request.AddRange(Convert.ToInt32(m_currFileSize.ToString()));
                    //重新定位后的响应
                    WebResponse v = request.GetResponse();
    
                    //取文件大小
                    m_totalFileSize = v.ContentLength; //+ m_currFileSize;
                    if (m_currFileSize >= m_totalFileSize)
                    {
                        fs.Close();
                        if (!string.IsNullOrEmpty(m_Md5))
                        {
                            string localFileMd5 = MD5Lib.CalcFileMD5(m_savePath);
                            if (!m_Md5.Equals(localFileMd5))
                            {
                                if (onValidateMD5Error != null)
                                {
                                    onValidateMD5Error(this, new ValidateMD5ErrorEventArgs(m_id, m_Md5, localFileMd5));
                                    return;
                                }
                            }
                            else
                            {
                                if (onDownloadEnd != null)
                                {
                                    onDownloadEnd(this, new DownloadendEventArgs(m_id, m_fileName, m_savePath,
                                        m_Md5, m_totalFileSize.ToString()));
                                }
                            }
                        }
                        return;
                    }
    
                    Stream rStream = v.GetResponseStream();
                    byte[] buffer = new byte[4096];
                    int len;
                    System.Threading.Timer m_timer = new System.Threading.Timer(new TimerCallback(FulshMemory));
                    m_timer.Change(100, 5000);
                    do
                    {
                        len = rStream.Read(buffer, 0, buffer.Length);
                        if (len > 0)
                            fs.Write(buffer, 0, len);
                        m_currFileSize += len;
                        m_HandlerData += len;
                        if (onDownloadIng != null)
                            onDownloadIng(this, new DownloadIngEventArgs(m_id,m_totalFileSize, len, m_currFileSize, m_speed));
                    } while (len > 0 && !m_isStop);
                    fs.Close();
                    rStream.Close();
                    if (!m_isStop)
                    {
                        if (!string.IsNullOrEmpty(m_Md5))
                        {
                            string localFileMd5 = MD5Lib.CalcFileMD5(m_savePath);
                            if (!m_Md5.Equals(localFileMd5))
                            {
                                if (onValidateMD5Error != null)
                                {
                                    onValidateMD5Error(this, new ValidateMD5ErrorEventArgs(m_id, m_Md5, localFileMd5));
                                    return;
                                }
                            }
                            else
                            {
                                if (onDownloadEnd != null)
                                {
                                    onDownloadEnd(this, new DownloadendEventArgs(m_id, m_fileName, m_savePath,
                                        m_Md5, m_totalFileSize.ToString()));
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    fs.Close();
                    if (ex.Message.Contains("(416) Requested Range Not Satisfiable"))
                    {
                        if (!string.IsNullOrEmpty(m_Md5))
                        {
                            string localFileMd5 = MD5Lib.CalcFileMD5(m_savePath);
                            if (!m_Md5.Equals(localFileMd5))
                            {
                                if (onValidateMD5Error != null)
                                {
                                    onValidateMD5Error(this, new ValidateMD5ErrorEventArgs(m_id, m_Md5, localFileMd5));
                                    return;
                                }
                            }
                            else
                            {
                                if (onDownloadEnd != null)
                                {
                                    onDownloadEnd(this, new DownloadendEventArgs(m_id, m_fileName, m_savePath,
                                        m_Md5, m_totalFileSize.ToString()));
                                }
                            }
                        }
                    }
                    else
                    {
                        if (onException != null)
                            onException(this, new ExceptionEventArgs(m_id,"文件传输时出现的异常", ex));
                    }
                }
            }
            /// <summary>
            /// 在归定的时间收到的数据
            /// </summary>
            private long m_HandlerData = 0;
            private string m_speed = "0k/s";
            /// <summary>
            /// 定时处理
            /// </summary>
            /// <param name="o"></param>
            private void FulshMemory(object o)
            {
                if (m_HandlerData != 0)
                {
                    m_speed = Util.HRSize(m_HandlerData / 5) + "/s";
                }
                m_HandlerData = 0;
            }
    
            /// <summary>
            /// 停止下载文件
            /// </summary>
            public void StopDownloadFile()
            {
                m_isStop = true;
            }
            #endregion<end方法>
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Print.DownloadFile
    {
        /// <summary>
        /// 文件下载结束
        /// </summary>
        public class DownloadendEventArgs : EventArgs
        {
            /// <summary>
            ///  构造方法
            /// </summary>
            /// <param name="id">文件信息在数据库保存的Id</param>
            /// <param name="fileName">文件名</param>
            /// <param name="localPath">保存的本地路径,包含文件名</param>
            /// <param name="md5">文件的MD5值</param>
            /// <param name="fileSize">文件大小</param>
            public DownloadendEventArgs(string id,string fileName, string localPath,string md5,string fileSize)
            {
                _fileName = fileName;
                _localPath = localPath;
                _id = id;
                _fileSize = fileSize;
                _md5 = md5;
            }
            private string _id;
            /// <summary>
            /// 获取文件信息在数据库保存的Id
            /// </summary>
            public string Id
            {
                get { return _id; }
            }
            private string _fileName;
            /// <summary>
            /// 获取下载的文件名
            /// </summary>
            public string FileName
            {
                get { return _fileName; }
            }
    
            private string _localPath;
            /// <summary>
            /// 获取保存在本地的路径
            /// </summary>
            public string LocalPath
            {
                get { return _localPath; }
            }
            private string _md5;
            /// <summary>
            /// 获取文件的MD5值
            /// </summary>
            public string Md5
            {
                get { return _md5; }
            }
            private string _fileSize;
            /// <summary>
            /// 获取文件的大小
            /// </summary>
            public string FileSize
            {
                get { return _fileSize; }
            }
        }
    }
    DownloadendEventArgs
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Print.DownloadFile
    {
        /// <summary>
        /// 文件正在下载
        /// </summary>
        public class DownloadIngEventArgs:EventArgs
        {
            /// <summary>
            /// 构造方法
            /// </summary>
            /// <param name="id">文件的ID</param>
            /// <param name="totalFileSize">文件总大小</param>
            /// <param name="currFileSize">本次下载数据</param>
            /// <param name="downloadFileEd">已经下载的文件大小</param>
            public DownloadIngEventArgs(string id,long totalFileSize, int currFileSize, long downloadFileEd,string speed)
            {
                this._id = id;
                this._totalFileSize = totalFileSize;
                this._currFileSize = currFileSize;
                this._downloadFileSizeEd = downloadFileEd;
                this._speed = speed;
            }
            private string _id;
            /// <summary>
            /// 获取文件的ID
            /// </summary>
            public string Id
            {
                get { return _id; }
            }
            private long _totalFileSize;
            /// <summary>
            /// 获取文件总大小
            /// </summary>
            public long TotalFileSize
            {
                get { return _totalFileSize; }
            }
            private int _currFileSize;
            /// <summary>
            /// 获取本次下载的大小
            /// </summary>
            public int CurrFileSize
            {
                get { return _currFileSize; }
            }
            private long _downloadFileSizeEd;
            /// <summary>
            /// 获取已经下载的文件大小
            /// </summary>
            public long DownloadFileSizeEd
            {
                get { return _downloadFileSizeEd; }
            }
            private string _speed;
            /// <summary>
            /// 获取下载速度
            /// </summary>
            public string Speed
            {
                get { return _speed; }
            }
        }
    }
    DownloadIngEventArgs
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Print.DownloadFile
    {
        public class ExceptionEventArgs : EventArgs
        {
            /// <summary>
            /// 构造方法
            /// </summary>
            /// <param name="id">文件的ID</param>
            /// <param name="info">抛出异常的描述</param>
            /// <param name="ex">抛出的异常对象</param>
            public ExceptionEventArgs(string id,string info, Exception ex)
            {
                this._id = id;
                this._info = info;
                this._ex = ex;
            }
            private string _id;
            /// <summary>
            /// 获取文件信息保存在数据库中的Id
            /// </summary>
            public string Id
            {
                get { return _id; }
            }
    
            private string _info;
            /// <summary>
            /// 获取抛出异常的描述
            /// </summary>
            public string Info
            {
                get { return _info; }
            }
            private Exception _ex;
            /// <summary>
            /// 抛出异常对象
            /// </summary>
            public Exception Ex
            {
                get { return _ex; }
            }
        }
    }
    ExceptionEventArgs
    using System;
    using System.Security.Cryptography;
    using System.IO;
    
    namespace Print.DownloadFile
    {
        public class MD5Lib
        {
            private static MD5 md5 = new MD5CryptoServiceProvider();
            public MD5Lib()
            {
            }
    
            private static string MD5ByteToStr(byte[] b)
            {
                string result = "";
                for (int i = 0; i < b.Length; i++)
                {
                    result += b[i].ToString("X2");
                }
                return result;
            }
            /// <summary>
            /// 取文件的MD5
            /// </summary>
            /// <param name="fileName"></param>
            /// <returns></returns>
            public static string CalcFileMD5(string fileName)
            {
                Stream stream = File.OpenRead(fileName);
                return CalcStreamMD5(stream);
            }
            /// <summary>
            /// 取流的MD5
            /// </summary>
            /// <param name="stream"></param>
            /// <returns></returns>
            public static string CalcStreamMD5(Stream stream)
            {
                byte[] md5Hash = md5.ComputeHash(stream);
                stream.Close();
                return MD5ByteToStr(md5Hash);
            }
            /// <summary>
            /// 取字符串的MD5
            /// </summary>
            /// <param name="str"></param>
            /// <returns></returns>
            public static string CalcStringMD5(string str)
            {
                byte[] source = System.Text.Encoding.Default.GetBytes(str);
                byte[] md5Hash = md5.ComputeHash(source);
                return MD5ByteToStr(md5Hash);
            }
        }
    }
    MD5Lib
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Print.DownloadFile
    {
        public class Util
        {
            #region<将文件大小转换成可读大小>
            /// <summary>
            /// 将文件的大小转换成可读的大小
            /// </summary>
            /// <param name="lBytes"></param>
            /// <returns></returns>
            public static string HRSize(long lBytes)
            {
                StringBuilder sb = new StringBuilder();
                string strUnits = "Bytes";
                float fAdjusted = 0.0F;
    
                if (lBytes > 1024)
                {
                    if (lBytes < 1024 * 1024)
                    {
                        strUnits = "KB";
                        fAdjusted = Convert.ToSingle(lBytes) / 1024;
                    }
                    else
                    {
                        strUnits = "MB";
                        fAdjusted = Convert.ToSingle(lBytes) / 1048576;
                    }
                    sb.AppendFormat("{0:0.0} {1}", fAdjusted, strUnits);
                }
                else
                {
                    fAdjusted = Convert.ToSingle(lBytes);
                    sb.AppendFormat("{0:0} {1}", fAdjusted, strUnits);
                }
                return sb.ToString();
            }
            #endregion<结束文件大小的转换>
        }
    }
    Util
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Print.DownloadFile
    {
        public class ValidateMD5ErrorEventArgs :EventArgs
        {
            /// <summary>
            /// 构造方法
            /// </summary>
            /// <param name="id">文件信息保存在数据库中的Id</param>
            /// <param name="availaMD5">用于验证文件有效的MD5</param>
            /// <param name="localFileMD5">文件下载完后本地的MD5</param>
            public ValidateMD5ErrorEventArgs(string id,string availaMD5, string localFileMD5)
            {
                this._availaMD5 = availaMD5;
                this._localFileMD5 = localFileMD5;
                this._id = id;
            }
            private string _id;
            /// <summary>
            /// 获取文件信息保存在数据库中的Id
            /// </summary>
            public string Id
            {
                get { return _id; }
            }
            private string _availaMD5;
            /// <summary>
            /// 获取有效的MD5值
            /// </summary>
            public string AvailaMD5
            {
                get { return _availaMD5; }
            }
            private string _localFileMD5;
            /// <summary>
            /// 获取下载完后本地的MD5值
            /// </summary>
            public string LocalFileMD5
            {
                get { return _localFileMD5; }
            }
        }
    }
    ValidateMD5ErrorEventArgs
  • 相关阅读:
    基于SPA的网页授权流程(微信OAuth2)
    用CSS3制作尖角标签按钮样式
    关于WebAPI跨域踩到的一点坑
    .net webapi跨域方法整理
    使用 JavaScript 截屏
    关于anguar2微信支付问题
    sql操作语句
    mysql5.7初始化密码报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before
    linux上安装mysql5.7
    git 常用命令
  • 原文地址:https://www.cnblogs.com/lusunqing/p/3151277.html
Copyright © 2011-2022 走看看