📄 downloadfile.cs
字号:
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security;
using System.Threading;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Data;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
namespace Cblang.HttpDownload
{
/// <summary>
/// Class for download thread
/// </summary>
public class DownloadFile
{
private DownloadFileInfo _fileInfo;
private Thread[] _subThreads;
private int _threadFinishedCount;
private int _threadNumber;
private bool _overrideFile = false; //不覆盖同名文件
private bool _isStopped = true;
/// <summary>
/// 接收数据委托
/// </summary>
public EventHandler<DownLoadEventArgs> DataReceived;
/// <summary>
/// 下载完成事件
/// </summary>
public event EventHandler Finished;
/// <summary>
/// 线程完成事件
/// </summary>
public event EventHandler ThreadFinished;
/// <summary>
/// 下载的文件信息
/// </summary>
public DownloadFileInfo FileInfo
{
get { return _fileInfo; }
}
/// <summary>
/// 下载后是否翻盖同名文件
/// </summary>
public bool OverrdeFile
{
get { return _overrideFile; }
set { _overrideFile = value; }
}
/// <summary>
/// 新建下载..
/// </summary>
/// <param name="requestURL">要下载文件的URL</param>
/// <param name="fileName">本地文件名</param>
/// <param name="threadNumber">使用的线程数</param>
public DownloadFile(string requestURL, string fileName, int threadNumber)
{
// Create download file info
_fileInfo = new DownloadFileInfo(requestURL, fileName);
if (threadNumber <= 0)
{
threadNumber = 5;//Defualt value
}
this._threadNumber = threadNumber;
}
/// <summary>
///
/// </summary>
/// <param name="fileName"></param>
public DownloadFile(string fileName)
{
DownloadFileInfo fileInfo = CreateDownloadFile(fileName);
_fileInfo = fileInfo;
this._threadNumber = _fileInfo.Packets.Length;
}
//public DownloadFile(DownloadFileInfo fileInfo)
//{
// _fileInfo = fileInfo;
// this.threadNumber = _fileInfo.Packets.Length;
//}
/// <summary>
/// Start to download
/// </summary>
///
public void Start()
{
if (_isStopped)
{
_isStopped = false;
_threadFinishedCount = 0;
if (_fileInfo.Packets == null)
{
InitFileDownInfo();
}
StartSubThreads();
}
}
/// <summary>
/// Check url to get download file info
/// </summary>
/// <returns></returns>
private void InitFileDownInfo()
{
//Create request
HttpWebRequest hwrq = (HttpWebRequest)WebRequest.Create(_fileInfo.RequestURL);
using (HttpWebResponse hwrp = (HttpWebResponse)hwrq.GetResponse())
{
//Get file size info
long L = hwrp.ContentLength;
L = ((L == -1) || (L > 0x7fffffff)) ? ((long)0x7fffffff) : L;
//Check whether this url is supported to be multi-threads download
bool blnMulti = (hwrp.Headers["Accept-Ranges"] != null && hwrp.Headers["Accept-Ranges"] == "bytes");
if (!blnMulti)
{
_threadNumber = 1;
}
_fileInfo.InitPackets((int)L, _threadNumber);
}
}
/// <summary>
/// Start sub-threads to download file
/// </summary>
private void StartSubThreads()
{
_subThreads = new Thread[this._threadNumber];
for (int i = 0; i < _threadNumber; i++)
{
Packet packet = _fileInfo.Packets[i];
if (packet.LoadSize + packet.From <= packet.To)
{
_subThreads[i] = new Thread(new ThreadStart(Download));
_subThreads[i].Name = i.ToString();
_subThreads[i].Start();
}
else
{
_threadFinishedCount++;
Debug.WriteLine(string.Format("Thread NO:{0} sends finish-info!", i.ToString()));
}
}
}
/// <summary>
/// Function for sub-thread
/// </summary>
private void Download()
{
int threadNO = int.Parse(System.Threading.Thread.CurrentThread.Name);
Packet packet = _fileInfo.Packets[threadNO];
//if (packet.LoadSize + packet.From > packet.To)
//{
// Debug.WriteLine(string.Format("Thread NO:{0} sends finish-info!", threadNO));
// EventHandler finishHandle = ThreadFinished;
// if (finishHandle != null)
// {
// finishHandle(this, EventArgs.Empty);
// }
// return;
//}
Debug.WriteLine(string.Format("Thread NO:{0} begins to download!", threadNO));
// Creat request by url
HttpWebRequest hwrq = (HttpWebRequest)WebRequest.Create(new Uri(_fileInfo.RequestURL));
// Go to download position
hwrq.AddRange(packet.LoadSize + packet.From, packet.To);
// Get response from request
using (HttpWebResponse hwrp = (HttpWebResponse)hwrq.GetResponse())
{
// download and write data from
Debug.WriteLine(string.Format("Thread NO:{0} call function named DownloadData!", threadNO));
using (Stream sReader = hwrp.GetResponseStream())
{
DownloadData(sReader, threadNO, packet);
}
}
}
//Download data through web request
private void DownloadData(Stream sReader, int threadNO, Packet packet)
{
using (FileStream sw = new FileStream(_fileInfo.FileName + DownloadFileInfo.FilenameExt, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
{
int readCount = 0;
sw.Position = packet.From + packet.LoadSize;
int position = packet.From + packet.LoadSize;
while (!_isStopped && position <= packet.To)
{
Debug.WriteLine(string.Format("Thread NO:{0} reads data!", threadNO));
// Read data
readCount = sReader.Read(packet.Buffer, 0, Packet.BUFFER_SIZE);
if (readCount <= 0)
{
break;
}
Debug.WriteLine(string.Format("Thread NO:{0} writes data!", threadNO));
// Write data
// sw.Position = packet.LoadSize + packet.From;
sw.Write(packet.Buffer, 0, readCount);
sw.Flush();
packet.LoadSize += readCount;
_fileInfo.BlockLeftSize += readCount;
Debug.WriteLine(string.Format("Thread NO:{0} writes {1} data!", threadNO, readCount));
// Call back
EventHandler<DownLoadEventArgs> receivedHandler = DataReceived;
if (receivedHandler != null)
{
Debug.WriteLine(string.Format("Thread NO:{0} send callback info!", threadNO));
receivedHandler(this, new DownLoadEventArgs(
_fileInfo, position, readCount, threadNO));
}
position += readCount;
}
}
if (_isStopped)
{
return;
}
Debug.WriteLine(string.Format("Thread NO:{0} sends finish-info!", threadNO));
EventHandler finishHandle = ThreadFinished;
if (finishHandle != null)
{
finishHandle(this, EventArgs.Empty);
}
_threadFinishedCount++;
if (_threadFinishedCount == _subThreads.Length)
{
DownloadFinished();
}
}
/// <summary>
/// Thread download finished
/// </summary>
private void DownloadFinished()
{
// Some download thread finished
if (_overrideFile && File.Exists(_fileInfo.FileName))
{
File.Delete(_fileInfo.FileName);
}
string filename = GetNewFilename(_fileInfo.FileName);
File.Move(_fileInfo.FileName + DownloadFileInfo.FilenameExt, filename);
EventHandler handler = Finished;
if (handler != null)
{
handler(_fileInfo, EventArgs.Empty);
}
}
/// <summary>
/// 停止下载
/// </summary>
public void Stop()
{
if (!_isStopped)
{
_isStopped = true;
for (int i = 0; i < _subThreads.Length; i++)
{
if ((_subThreads[i] != null) && (_subThreads[i].ThreadState == System.Threading.ThreadState.Running))
{
_subThreads[i].Join(10);
}
Debug.WriteLine(string.Format("Thread NO:{0} is stopped!", i));
}
string name = MD5Helper.MD5Encrypt(_fileInfo.RequestURL);
SaveFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name));
}
}
/// <summary>
/// 保存下载状态到文件
/// </summary>
/// <param name="fileName"></param>
private void SaveFile(string fileName)
{
BinaryFormatter serializer = new BinaryFormatter();
using (System.IO.MemoryStream memStream = new System.IO.MemoryStream())
{
serializer.Serialize(memStream, _fileInfo);
using (FileStream sw = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Write))
{
memStream.WriteTo(sw);
}
}
}
/// <summary>
/// 载入下载日志文件...
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static DownloadFileInfo CreateDownloadFile(string fileName)
{
using (FileStream sw = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] buffer = new byte[sw.Length];
sw.Read(buffer, 0, buffer.Length);
using (System.IO.MemoryStream memStream = new System.IO.MemoryStream(buffer))
{
BinaryFormatter deserializer = new BinaryFormatter();
return (DownloadFileInfo)(deserializer.Deserialize(memStream));
}
}
}
/// <summary>
/// 得到不重复的文件名
/// </summary>
/// <returns></returns>
public static string GetNewFilename(string filename)
{
if (File.Exists(filename))
{
string newname = filename;
int i = 0;
int lastPoint = filename.LastIndexOf('.');
do
{
i++;
if (lastPoint < 1)
{
newname = filename + "(" + i + ")";
}
else
{
newname = filename.Substring(0, lastPoint) + "(" + i + ")" + filename.Substring(lastPoint);
}
}
while (File.Exists(newname));
return newname;
}
else
{
return filename;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -