XAsset 异步下载资源 解析

工具

资源服务器 hfs网络文件服务器(百度即可下载 hfs网络文件服务器(个人HTTP文件服务器)下载 v2.3 免费绿色版 - 比克尔下载 上传资源)

 Unity 

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using UnityEngine;

//namespace VEngine
//{
    public enum DownloadStatus
    {
        Wait,
        Progressing,
        Success,
        Failed
    }

    public class DownloadInfo
    {
        public uint crc;
        public string savePath;
        public long size;
        public string url;
    }


    public class DownLoadManager
    {


        /// <summary>
        /// 最大同时下载数
        /// </summary>
        public static uint MaxDownLoads = 10;

        /// <summary>
        /// 读取速度
        /// </summary>
        public static uint ReadBufferSize = 1024 * 4;

        /// <summary>
        /// 准备  下载
        /// </summary>
        public static readonly List<Download> Prepared = new List<Download>();

        /// <summary>
        /// 正在  下载
        /// </summary>
        public static readonly List<Download> Progressing = new List<Download>();

        /// <summary>
        /// 缓存下载
        /// </summary>
        public static readonly Dictionary<string, Download> Cache = new Dictionary<string, Download>();


        /// <summary>
        /// 是否有正在下载的任务
        /// </summary>
        public static bool Working => Progressing.Count > 0;


        //每秒下载速度
        public static long TotalBandwidth { get; private set; }

        /// <summary>
        /// 总下载大小
        /// </summary>
        public static long TotalDownloadedBytes
        {
            get
            {
                var value = 0L;
                foreach (var item in Cache)  {  value += item.Value.downloadedBytes; }
                return value;
            }
        }

        /// <summary>
        /// 总大小
        /// </summary>
        public static long TotalSize
        {
            get
            {
                var value = 0L;
                foreach (var item in Cache){   value += item.Value.info.size; }
                return value;
            }
        }

        private static float lastSampleTime;//最后下载时间
        private static long lastTotalDownLoadedBytes;//最后下载字节数

        public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain,
SslPolicyErrors spe)
        {
            return true;
        }

        public static void ClearAllDownloads()
        {
            foreach (var download in Progressing)
            {

            }

            Prepared.Clear();
            Progressing.Clear();
            Cache.Clear();
        }


        public static Download DownloadAsync(string url,string savePath,long size = 0,uint crc = 0,Action<Download> complete=null)
        {
            return DownloadAsync(new DownloadInfo
            {
                url = url,
                savePath = savePath,
                crc = crc,
                size = size
            }, complete);
        }

        public static Download DownloadAsync(DownloadInfo info, Action<Download> complete)
        {
            Download download;
            if (!Cache.TryGetValue(info.url,out download))
            {
                download = new Download(info);
                Prepared.Add(download);
                Cache.Add(info.url, download);
            }
            else
            {
                UnityEngine.Debug.LogWarning($"Download url {info.url} already exist.");
            }

            if (complete != null)
            {
                download.completed += complete;
            }
            return download;
        }


        public static void UpdateAll()
        {
            //把准备下载列表的  加入正在下载的列表中
            if (Prepared.Count > 0)
            {
                //取剩余可  准备下载数   受最大数量限制
                for (int i = 0; i < Mathf.Min(Prepared.Count,MaxDownLoads - Progressing.Count); i++)
                {
                    var download = Prepared[i];
                    Prepared.RemoveAt(i);
                    i--;
                    Progressing.Add(download);
                    download.Start();//启动下载
                }
            }

            //刷新正在下载列表的  下载进度  和移除已经下载完毕的 任务
            if (Progressing.Count > 0)
            {
                for (int index = 0; index < Progressing.Count; index++)
                {
                    var download = Progressing[index];
                    if (download.updated != null) download.updated(download);

                    if (download.isDone)
                    {
                        if (download.status == DownloadStatus.Failed)
                        {
                            Debug.LogError($"Unable to download {download.info.url} with error { download.error}");
                        }
                        else
                        {
                            Debug.Log($"Success to download { download.info.url}");
                        }
                        Progressing.RemoveAt(index);
                        index--;
                        download.Complete();
                    }

                }


                //一秒间隔 刷新 进度
                if (Time.realtimeSinceStartup  - lastSampleTime >= 1)
                {
                    lastTotalDownLoadedBytes = TotalDownloadedBytes;
                    lastSampleTime = Time.realtimeSinceStartup;
                }
            }
            else
            {
                if (Cache.Count <= 0) return;

                Cache.Clear();
                lastTotalDownLoadedBytes = 0;
                lastSampleTime = Time.realtimeSinceStartup;
 
            }
        }

    }

    public class Download : CustomYieldInstruction
    {
        public Action<Download> completed { get; set; }
        public Action<Download> updated { get; set; }
        /// <summary>
        /// 下载状态
        /// </summary>
        public DownloadStatus status { get; private set; }

        /// <summary>
        /// 下载信息
        /// </summary>
        public DownloadInfo info { get; private set; }

        private Thread _thread;
        private FileStream writer;
        private readonly byte[] _readBuffer = new byte[DownLoadManager.ReadBufferSize];
        public bool isDone => status == DownloadStatus.Failed || status == DownloadStatus.Success;
        public long downloadedBytes { get; private set; }//已经下载的字节数
        public float process => downloadedBytes * 1f / info.size;//下载进度
        public override bool keepWaiting =>!isDone;
        public string error { get; private set; }



        public Download(DownloadInfo info)
        {
            this.info = info;
            status = DownloadStatus.Wait;
            downloadedBytes = 0;
        }



        private WebRequest GetHttpWebRequest()
        {
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(info.url) ;
            httpWebRequest.ProtocolVersion = HttpVersion.Version10;
            if (downloadedBytes > 0) httpWebRequest.AddRange(downloadedBytes);
            return httpWebRequest;
        }

        private WebRequest CreateWebRequest()
        {
            WebRequest request;
            if (info.url.StartsWith("https",StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = DownLoadManager.CheckValidationResult;
            }
            request = GetHttpWebRequest();

            return request;
        }

        private void DownLoading()
        {
            var request = CreateWebRequest();
            using (var response = request.GetResponse())
            {
                if (response.ContentLength > 0)
                {
                    //初始化下载文件 大小
                    if (info.size == 0) info.size = response.ContentLength + downloadedBytes;

                    using (var reader = response.GetResponseStream())
                    {
                        if (downloadedBytes < info.size)
                        {
                            while (status == DownloadStatus.Progressing)
                            {
                                if (ReadToEnd(reader)) break;
                            }
                        }
                    }
                }
                else
                {
                    status = DownloadStatus.Success;
                }
            }
        }

        private bool ReadToEnd(Stream reader)
        {
            var len = reader.Read(_readBuffer, 0, _readBuffer.Length);
            if (len > 0)
            {
                writer.Write(_readBuffer, 0, len);
                downloadedBytes += len;
                return false;
            }
            return true;
        }


        private void CloseWrite()
        {
            if (writer != null)
            {
                writer.Flush();
                writer.Close();
            }
        }




        private void Run()
        {
            try
            {
                DownLoading();//下载 和 写入
                CloseWrite();
                if (status == DownloadStatus.Failed) return;

                //大小不匹配下载失败
                if (downloadedBytes != info.size) 
                {
                    error = $"Download length {downloadedBytes} mismatch to {info.size}";
                    status = DownloadStatus.Failed;
                    return;
                }


                //CRC校验
                if (info.crc != 0)
                {
                    //var crc = Utility.ComputeCRC32(info.savePath);
                    //if (info.crc != crc)
                    //{
                    //    File.Delete(info.savePath);
                    //    error = $"Download crc {crc} mismatch to {info.crc}";
                    //    status = DownloadStatus.Failed;
                    //    return;
                    //}
                }

                status = DownloadStatus.Success;
            }
            catch (Exception e)
            {
                CloseWrite();
                error = e.Message;
                status = DownloadStatus.Failed;
            }
        }

        public void Start()
        {
            //等待状态才会 启动
            if (status != DownloadStatus.Wait) return;

            Debug.Log($" start download {info.url}");
            status = DownloadStatus.Progressing;

            var file = new FileInfo(info.savePath);
            //断点续传  还是怎么样
            if (file.Exists && file.Length > 0)
            {
                if (info.size > 0 && file.Length == info.size)
                {
                    status = DownloadStatus.Success;
                    return;
                }

                writer = File.OpenWrite(info.savePath);
                downloadedBytes = writer.Length - 1;//只取了  -1长度
                if (downloadedBytes > 0)
                {
                    writer.Seek(-1, SeekOrigin.End);
                }
            }
            else
            {
                var dir = Path.GetDirectoryName(info.savePath);
                if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir);

                writer = File.Create(info.savePath);
            }


            _thread = new Thread(Run)
            {
                IsBackground = true
            };

            _thread.Start();
        }



        public void Retry()
        {
            status = DownloadStatus.Wait;
            Start();
        }

        public void Pause()
        {
            status = DownloadStatus.Wait;
        }
        public void UnPause()
        {
            Retry();
        }
        public void Cancel()
        {
            error = "User Cancel.";
            status = DownloadStatus.Failed;
        }
        public void Complete()
        {
            if (completed != null)
            {
                completed.Invoke(this);
                completed = null;
            }
        }
    }
//}
//测试下载
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class TestSomething : MonoBehaviour
{

    [ContextMenu("SceneName")]
    void Scene()
    {
        TempCopy();
    }
    public void TempCopy()
    {
        string path = @"D:\testDownload\dog.gif";
        for (int i = 0; i < 100; i++)
        {
            CopyDirIntoDestDirectory(path, Path.Combine(@"D:\testDownload",$"dog{i}.gif"), true);
        }
    }

    public void CopyDirIntoDestDirectory(string sourceFileName, string destFileName, bool overwrite)
    {
        File.Copy(sourceFileName, destFileName, overwrite);
    }


    // Start is called before the first frame update
    void Start()
    {
        TestXAssetDownload();
    }
    private Download download;
    void TestXAssetDownload()
    {

        for (int i = 0; i < 30; i++)
        {
            var index = i;
            DownLoadManager.DownloadAsync(new DownloadInfo()
            {
                savePath = Path.Combine(Application.dataPath, $"dog{index}.gif"),
                url = @"http://10.0.0.155:8000/" + $"dog{index}.gif"
            }, (d) => { print($"下载dog{index}.gif完毕"); }); ;
        }


    }
    // Update is called once per frame
    void Update()
    {
        DownLoadManager.UpdateAll();
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值