using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; /// /// 用于处理文件下载 /// internal class XDownloadHandler: DownloadHandlerScript { string m_SavePath = ""; string m_TempFilePath = ""; FileStream fs; public long totalFileLen { get; private set; } public long downloadedFileLen { get; private set; } public string fileName { get; private set; } public string dirPath { get; private set; } #region 事件 /// /// 每次下载到数据后回调进度 /// public Action OnProgress = null; /// /// 当下载完成后回调下载的文件位置 /// public Action OnFinish = null; #endregion /// /// 初始化下载句柄,定义每次下载的数据上限为1M /// /// 保存到本地的文件路径 public XDownloadHandler(string filePath) : base(new byte[1024 * 1024]) { m_SavePath = filePath.Replace('\\', '/'); fileName = m_SavePath.Substring(m_SavePath.LastIndexOf('/') + 1); dirPath = m_SavePath.Substring(0, m_SavePath.LastIndexOf('/')); m_TempFilePath = Path.Combine(dirPath, fileName + ".temp"); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } fs = new FileStream(m_TempFilePath, FileMode.Append, FileAccess.Write); downloadedFileLen = fs.Length; } /// /// 从网络获取数据时候的回调,每帧调用一次 /// /// 接收到的数据字节流,总长度为构造函数定义的200kb,并非所有的数据都是新的 /// 接收到的数据长度,表示data字节流数组中有多少数据是新接收到的,即0-dataLength之间的数据是刚接收到的 /// 返回true为继续下载,返回false为中断下载 protected override bool ReceiveData(byte[] data, int dataLength) { if (data == null || data.Length == 0) { Debug.LogFormat("【下载中】 下载文件{0}中,没有获取到数据,下载终止", fileName); return false; } fs?.Write(data, 0, dataLength); downloadedFileLen += dataLength; OnProgress?.Invoke(downloadedFileLen, totalFileLen); return true; } /// /// 当接受数据完成时的回调 /// protected override void CompleteContent() { OnDispose(); //Debug.LogFormat("【下载完成】 完成对{0}文件的下载,保存路径为{1}", fileName, m_SavePath); if (File.Exists(m_TempFilePath)) { if (File.Exists(m_SavePath)) File.Delete(m_SavePath); File.Move(m_TempFilePath, m_SavePath); } else { Debug.LogFormat("【下载失败】 下载文件{0}时失败", fileName); } OnFinish?.Invoke((int)downloadedFileLen); } public void OnDispose() { fs?.Close(); fs?.Dispose(); } /// /// 请求下载时的第一个回调函数,会返回需要接收的文件总长度 /// /// 如果是续传,则是剩下的文件大小;本地拷贝则是文件总长度 protected override void ReceiveContentLengthHeader(ulong contentLength) { if (contentLength == 0) { Debug.Log("【下载已经完成】"); CompleteContent(); } base.ReceiveContentLengthHeader(contentLength); totalFileLen = (long)contentLength + downloadedFileLen; } public void ErrorDispose() { fs.Close(); fs.Dispose(); if (File.Exists(m_TempFilePath)) { File.Delete(m_TempFilePath); } Dispose(); } public override void Dispose() { OnFinish = null; OnProgress = null; base.Dispose(); } }