using Common.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
namespace Common.system
{
///
/// 下载方法
/// 创建人:赵耀
/// 创建时间:2018年10月30日
///
public class DownloadManager
{
private long _fromIndex; //开始下载的位置
private bool _isRun; //是否正在进行
private DownloadInfoModel _dlInfo;
private List _dls = new List();
///
/// 开始下载
///
public event Action OnStart;
///
/// 停止下载
///
public event Action OnStop;
///
/// 下载进度
///
public event Action OnDownload;
///
/// 下载完成
///
public event Action OnFinsh;
///
/// 断开网络连接
///
public event Action OnDisconnect;
public DownloadManager(DownloadInfoModel dlInfo)
{
this._dlInfo = dlInfo;
}
///
/// 暂停
///
public void Stop()
{
_isRun = false;
_dls.ForEach(dl => dl.Stop());
OnStopHandler();
}
///
/// 开始下载
///
public void Start()
{
_dlInfo.isReStart = false;
WorkStart();
}
///
/// 重新下载
///
public void ReStart()
{
_dlInfo.isReStart = true;
WorkStart();
}
///
/// 下载
///
private void WorkStart()
{
new Action(() =>
{
if (_dlInfo.isReStart)
{
Stop();
}
while (_dls.Where(dl => !dl.isStopped).Count() > 0)
{
if (_dlInfo.isReStart)
{
Thread.Sleep(100);
}
else
{
return;
}
}
_isRun = true;
OnStartHandler();
//首次任务或者不支持断点续传的进入
if (_dlInfo.isNewTask || (!_dlInfo.isNewTask && !_dlInfo.IsSupportMultiThreading))
{
try
{
//第一次请求获取一小块数据,根据返回的情况判断是否支持断点续传
using (System.Net.WebResponse rsp = ZHttpUtil.Download(
_dlInfo.downloadUrlList[0],
0,
0,
_dlInfo.method
))
{
//获取文件名,如果包含附件名称则取下附件,否则从url获取名称
string disposition = rsp.Headers["Content-Disposition"];
try
{
if (disposition != null)
{
_dlInfo.fileName = disposition.Split('=')[1];
}
else
{
_dlInfo.fileName = Path.GetFileName(rsp.ResponseUri.AbsolutePath);
}
}
catch (Exception) //无法获取文件名时 使用传入保存名称
{
_dlInfo.fileName = _dlInfo.saveFileName;
}
//默认给流总数
_dlInfo.count = rsp.ContentLength;
//尝试获取 Content-Range 头部,不为空说明支持断点续传
string contentRange = rsp.Headers["Content-Range"];
if (contentRange != null)
{
//支持断点续传的话,就取range 这里的总数
_dlInfo.count = long.Parse(rsp.Headers["Content-Range"].Split('/')[1]);
_dlInfo.IsSupportMultiThreading = true;
//生成一个临时文件名
//var tempFileName = Convert.ToBase64String(Encoding.UTF8.GetBytes(dlInfo.fileName)).ToUpper();
//tempFileName = tempFileName.Length > 32 ? tempFileName.Substring(0, 32) : tempFileName;
//dlInfo.tempFileName = "test"; //tempFileName + DateTime.Now.ToString("yyyyMMddHHmmssfff");
GetTaskInfo(_dlInfo);
}
else
{
//不支持断点续传则一开始就直接读完整流
Save(GetRealFileName(_dlInfo), rsp.GetResponseStream());
OnFineshHandler();
}
}
}
catch (Exception ex)
{
string errMessage = "【下载】(DownloadManager):" + ex.Message;
LogHelper.Logerror.Error(errMessage, ex);
OnDisconnectHandler();
return;
}
_dlInfo.isNewTask = false;
}
//如果支持断点续传采用这个
if (_dlInfo.IsSupportMultiThreading)
{
StartTask(_dlInfo);
//等待合并
while (_dls.Count(td => !td.isFinish) > 0 && _isRun)
{
Thread.Sleep(100);
}
if ((_dls.Count(td => !td.isFinish) == 0))
{
CombineFiles(_dlInfo);
OnFineshHandler();
}
}
}).BeginInvoke(null, null);
}
///
/// 合成文件
///
///
private void CombineFiles(DownloadInfoModel dlInfo)
{
string realFilePath = GetRealFileName(dlInfo);
//合并数据
byte[] buffer = new byte[2048];
int length;
using (FileStream fileStream = File.Open(realFilePath, FileMode.CreateNew))
{
for (int i = 0; i < dlInfo.TaskInfoList.Count; i++)
{
string tempFile = dlInfo.TaskInfoList[i].filePath;
using (FileStream tempStream = File.Open(tempFile, FileMode.Open))
{
while ((length = tempStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, length);
}
tempStream.Flush();
}
//File.Delete(tempFile);
}
}
}
///
/// 创建文件
///
///
///
private static string GetRealFileName(DownloadInfoModel dlInfo)
{
//创建正式文件名,如果已存在则加数字序号创建,避免覆盖
int fileIndex = 0;
string realFilePath = Path.Combine(dlInfo.saveDir, dlInfo.saveFileName);
while (File.Exists(realFilePath))
{
realFilePath = Path.Combine(dlInfo.saveDir, string.Format("{0}_{1}", fileIndex++, dlInfo.fileName));
}
return realFilePath;
}
private void StartTask(DownloadInfoModel dlInfo)
{
_dls = new List();
if (dlInfo.TaskInfoList != null)
{
foreach (TaskInfoModel item in dlInfo.TaskInfoList)
{
DownloadService dl = new DownloadService();
dl.OnDownload += OnDownloadHandler;
dl.OnDisconnect += OnDisconnectHandler;
_dls.Add(dl);
try
{
dl.Start(item, dlInfo.isReStart);
}
catch (Exception ex)
{
string errMessage = "【下载】(DownloadManager):" + ex.Message;
LogHelper.Logerror.Error(errMessage, ex);
}
}
}
}
///
/// 创建下载任务
///
///
private void GetTaskInfo(DownloadInfoModel dlInfo)
{
long pieceSize = (dlInfo.count) / dlInfo.taskCount;
dlInfo.TaskInfoList = new List();
//Random rand = new Random();
int urlIndex = 0;
for (int i = 0; i <= dlInfo.taskCount + 1; i++)
{
long from = (i * pieceSize);
if (from >= dlInfo.count)
{
break;
}
long to = from + pieceSize;
if (to >= dlInfo.count)
{
to = dlInfo.count;
}
dlInfo.TaskInfoList.Add(
new TaskInfoModel
{
method = dlInfo.method,
downloadUrl = dlInfo.downloadUrlList[urlIndex++],
filePath = Path.Combine(dlInfo.saveDir, dlInfo.tempFileName + ".temp" + i),
fromIndex = from,
toIndex = to
});
if (urlIndex >= dlInfo.downloadUrlList.Count)
{
urlIndex = 0;
}
}
}
///
/// 保存内容
///
///
///
private void Save(string filePath, Stream stream)
{
try
{
using (FileStream writer = File.Open(filePath, FileMode.Append))
{
using (stream)
{
int repeatTimes = 0;
byte[] buffer = new byte[1024];
int length;
while ((length = stream.Read(buffer, 0, buffer.Length)) > 0 && _isRun)
{
writer.Write(buffer, 0, length);
_fromIndex += length;
if (repeatTimes % 5 == 0)
{
writer.Flush(); //一定大小就刷一次缓冲区
OnDownloadHandler();
}
repeatTimes++;
}
writer.Flush();
OnDownloadHandler();
}
}
}
catch (Exception)
{
//异常也不影响
}
}
///
/// 开始下载
///
private void OnStartHandler()
{
new Action(() =>
{
if (OnStart != null)
{
OnStart.Invoke();
}
}).BeginInvoke(null, null);
}
///
/// 暂停下载
///
private void OnStopHandler()
{
new Action(() =>
{
OnStop?.Invoke();
}).BeginInvoke(null, null);
}
///
/// 下载完成
///
private void OnFineshHandler()
{
new Action(() =>
{
for (int i = 0; i < _dlInfo.TaskInfoList.Count; i++)
{
string tempFile = _dlInfo.TaskInfoList[i].filePath;
File.Delete(tempFile);
}
OnFinsh?.Invoke(_dlInfo.saveFileName);
}).BeginInvoke(null, null);
}
///
/// 下载进度
///
private void OnDownloadHandler()
{
new Action(() =>
{
long current = GetDownloadLength();
OnDownload?.Invoke(current, _dlInfo.count, _dlInfo.saveFileName);
}).BeginInvoke(null, null);
}
///
/// 断开网络连接
///
private void OnDisconnectHandler()
{
new Action(() =>
{
OnDisconnect?.Invoke(_dlInfo.saveFileName);
}).BeginInvoke(null, null);
}
///
/// 当前下载进度
///
///
public long GetDownloadLength()
{
if (_dlInfo.IsSupportMultiThreading)
{
return _dls.Sum(dl => dl.GetDownloadedCount());
}
else
{
return _fromIndex;
}
}
///
/// 获取保存文件名
///
///
public DownloadInfoModel GetFileInfo => _dlInfo;
}
}