转: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 = ;
/// <summary>
/// 当前已经下载的大小
/// </summary>
private long m_currFileSize = ;
/// <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('\\') + );
m_id = id;
}
#endregion<end构造方法> #region<方法>
/// <summary>
/// 开始下载文件
/// </summary>
public void StartDownloadFile()
{
m_isStop = false;
string filePath = m_savePath.Substring(, 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 > )
{
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 > )
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[];
int len;
System.Threading.Timer m_timer = new System.Threading.Timer(new TimerCallback(FulshMemory));
m_timer.Change(, );
do
{
len = rStream.Read(buffer, , buffer.Length);
if (len > )
fs.Write(buffer, , 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 > && !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 = ;
private string m_speed = "0k/s";
/// <summary>
/// 定时处理
/// </summary>
/// <param name="o"></param>
private void FulshMemory(object o)
{
if (m_HandlerData != )
{
m_speed = Util.HRSize(m_HandlerData / ) + "/s";
}
m_HandlerData = ;
} /// <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 = ; 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 > )
{
if (lBytes < * )
{
strUnits = "KB";
fAdjusted = Convert.ToSingle(lBytes) / ;
}
else
{
strUnits = "MB";
fAdjusted = Convert.ToSingle(lBytes) / ;
}
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
转:Http下载文件类 支技断点续传功能的更多相关文章
- php利用curl实现多进程下载文件类
批量下载文件一般使用循环的方式,逐一执行下载.但在带宽与服务器性能允许的情况下,使用多进程进行下载可以大大提高下载的效率.本文介绍PHP利用curl的多进程请求方法,实现多进程同时下载文件. 原理: ...
- Node.js mm131图片批量下载爬虫1.01 增加断点续传功能
这里的断点续传不是文件下载时的断点续传,而是指在爬行页面时有时会遇到各种网络中断而从中断前的页面及其数据继续爬行的过程,这个过程和断点续传原理上相似故以此命名.我的具体做法是:在下载出现故障或是图片已 ...
- asp.net mvc大文件上传、断点续传功能。
文件夹数据库处理逻辑 publicclass DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject(); ...
- Linux wget 命令下载文件
wget是Linux系统中用来下载文件的工具,其功能还是比较多的,能够下载单个文件,也可以分段下载,下面小编将针对wget命令的用法给大家做个实例介绍. 实例1 :下载单个文件 # wget http ...
- android 使用AsyncHttpClient框架上传文件以及使用HttpURLConnection下载文件
AsyncHttpClient开源框架android-async-http还是非常方便的. AsyncHttpClient该类通经常使用在android应用程序中创建异步GET, POST, PUT和 ...
- Linux下载——下载文件的命令
Linux下载——获取网络文件的命令 摘抄:本文主要学习了在Linux系统中如何下载文件的命令. wget命令 wget命令是一个用来下载文件的命令,可以在后台运行,在用户退出之后仍能继续下载,支持代 ...
- android多线程断点续传下载文件
一.目标 1.多线程抢占服务器资源下载. 2.断点续传. 二.实现思路. 假设分为三个线程: 1.各个线程分别向服务器请求文件的不同部分. 这个涉及Http协议,可以在Header中使用Range参数 ...
- 反射机制及开源框架xUitls的使用,使用HttpUtils通过断点续传下载文件
反射: Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性 Java反射机制主要提供下面几种用途: 1•在运行时判断 ...
- FTP文件上传 支持断点续传 并 打印下载进度(二) —— 单线程实现
这个就看代码,哈哈哈哈哈 需要用到的jar包是: <dependency> <groupId>commons-net</groupId> <artifact ...
随机推荐
- Hibernate的一个小应用
hibernate 第一步,导入hiberante需要用到的jar包,因为使用hibernate时候,有日志信息输出,hibernate本身没有日志输出的jar包,导入其他日志的jar包 不要忘记还有 ...
- mysql 数据表操作 目录
mysql 数据表操作 存储引擎介绍 mysql 使用存储引擎 mysql 数据表的增删改查 mysql 数据类型 mysql 约束条件
- python的第三方库
python的第三方库 https://www.lfd.uci.edu/~gohlke/pythonlibs/
- 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】
四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...
- wxPython:文本对话框TextEntryDialog
wxTextEntryDialog(wxWindow* parent, const wxString& message, const wxString& caption = " ...
- abap function module中的异常处理
1: 定义一个有异常抛出的function module. (zfm_moudle6), 该函数中有符合exceptions中的异常,将会自动将exceptions中的异常抛出. FUNCTION ...
- abap中结构体嵌套结构体。
1: 结构体中嵌套结构体. *&---------------------------------------------------------------------* *& Re ...
- C语言strcasecmp()函数:判断字符串是否相等(忽略大小写)
头文件:#include <string.h> 定义函数:int strcasecmp (const char *s1, const char *s2); 函数说明:strcasecmp( ...
- 银联卡中关于CVN/CVN2/ICVN的区别
银联China Union Pay,是中国唯一合法的卡组织机构,同时也是EMVCo成员.关于银联卡中CVN/CVN2/ICVN的区别,刚开始我自己不了解,但经过查找资料和请教其他人,对它们的概念也渐渐 ...
- centos7下git服务器端搭建
git的安装: yum 源仓库里的 Git 版本更新不及时,最新版本的 Git 是 1.8.3.1,但是官方最新版本已经到了 2.9.2.想要安装最新版本的的 Git,只能下载源码进行安装. 1. 查 ...