taochangchun 1 mēnesi atpakaļ
revīzija
99fe1cbbd7

+ 16 - 0
DownloadFileInfo.cs

@@ -0,0 +1,16 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using UnityEngine;
5
+
6
+namespace TModule.Runtime
7
+{
8
+    public class DownloadFileInfo
9
+    {
10
+        public string m_url;
11
+        public string m_savePath;
12
+        public Action<float, long, long> onProgress;
13
+        public Action<string> onErroe;
14
+        public Action onOver;
15
+    }
16
+}

+ 11 - 0
DownloadFileInfo.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: f78430bf86a047d45b47e688eb9a1f20
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: 

+ 159 - 0
DownloadManager.cs

@@ -0,0 +1,159 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using UnityEngine;
5
+
6
+namespace TModule.Runtime
7
+{
8
+    public class DownloadManager : MonoBehaviour
9
+    {
10
+        private List<DownloadRoutine> _downloadRoutines = new List<DownloadRoutine>();
11
+
12
+        private Queue<DownloadFileInfo> downloadFiles = new Queue<DownloadFileInfo>();
13
+
14
+        /// <summary>
15
+        /// 最大下载器数量
16
+        /// </summary>
17
+        public int m_maxCount = 5;
18
+
19
+        private void Awake()
20
+        {
21
+            for (int i = 0; i < m_maxCount; i++)
22
+            {
23
+                _downloadRoutines.Add(new DownloadRoutine());
24
+            }
25
+        }
26
+
27
+        /// <summary>
28
+        /// 暂停下载
29
+        /// </summary>
30
+        /// <param name="url"></param>
31
+        /// <param name="savePath"></param>
32
+        public void StopDownload(string url, string savePath)
33
+        {
34
+            _downloadRoutines.Find(p => p.DownLoadUrl == url && p.FileSavePath == savePath)?.StopDownload();
35
+        }
36
+
37
+        /// <summary>
38
+        /// 暂停下载
39
+        /// </summary>
40
+        /// <param name="fileInfo"></param>
41
+        public void StopDownload(DownloadFileInfo fileInfo)
42
+        {
43
+            StopDownload(fileInfo.m_url, fileInfo.m_savePath);
44
+        }
45
+
46
+        /// <summary>
47
+        /// 暂停所有下载
48
+        /// </summary>
49
+        public void StopAllDownload()
50
+        {
51
+            foreach (var item in _downloadRoutines)
52
+            {
53
+                if (!item.IsLeisure)
54
+                    item.StopDownload();
55
+            }
56
+        }
57
+
58
+        /// <summary>
59
+        /// 开始下载
60
+        /// </summary>
61
+        /// <param name="url"></param>
62
+        /// <param name="savePath"></param>
63
+        /// <param name="onProgress"></param>
64
+        /// <param name="onOver"></param>
65
+        /// <param name="onError"></param>
66
+        public void StartDownload(string url,string savePath,Action<float,long,long>onProgress=null,Action onOver=null,Action<string> onError=null)
67
+        {
68
+            StartDownload(new DownloadFileInfo
69
+            {
70
+                m_savePath = savePath,
71
+                m_url = url,
72
+                onErroe = onError,
73
+                onOver = onOver,
74
+                onProgress = onProgress
75
+            });
76
+        }
77
+
78
+        /// <summary>
79
+        /// 开始下载
80
+        /// </summary>
81
+        /// <param name="fileInfo"></param>
82
+        public void StartDownload(DownloadFileInfo fileInfo)
83
+        {
84
+            DownloadRoutine routine = GetLeisureDownloadRoutine(); 
85
+            if (routine == null)
86
+                downloadFiles.Enqueue(fileInfo);
87
+            else
88
+            {
89
+                routine.onProgress = fileInfo.onProgress;
90
+                routine.onDownloadOver = ()=> { fileInfo.onOver?.Invoke(); CheckIsOver();};
91
+                routine.onError = fileInfo.onErroe;
92
+                routine.StartDownload(fileInfo.m_url, fileInfo.m_savePath);
93
+            }
94
+        }
95
+
96
+        /// <summary>
97
+        /// 批量下载
98
+        /// </summary>
99
+        /// <param name="fileInfos"></param>
100
+        public void BatchDownload(IEnumerable<DownloadFileInfo> fileInfos)
101
+        {
102
+            foreach (var item in fileInfos)
103
+            {
104
+                StartDownload(item);
105
+            }
106
+        }
107
+
108
+        /// <summary>
109
+        /// 继续下载
110
+        /// </summary>
111
+        /// <param name="url"></param>
112
+        /// <param name="savePath"></param>
113
+        public void ContinueDownload(string url,string savePath)
114
+        {
115
+            _downloadRoutines.Find(p => p.DownLoadUrl == url && p.FileSavePath == savePath)?.ContinueDownload();
116
+        }
117
+
118
+        /// <summary>
119
+        /// 继续下载
120
+        /// </summary>
121
+        /// <param name="fileInfo"></param>
122
+        public void ContinueDownload(DownloadFileInfo fileInfo)
123
+        {
124
+            ContinueDownload(fileInfo.m_url, fileInfo.m_savePath);
125
+        }
126
+
127
+        /// <summary>
128
+        /// 全部继续下载
129
+        /// </summary>
130
+        public void ContinueAllDownload()
131
+        {
132
+            foreach (var item in _downloadRoutines)
133
+            {
134
+                if (!item.IsLeisure && item.IsStop)
135
+                    item.ContinueDownload();
136
+            }
137
+        }
138
+
139
+        private void CheckIsOver()
140
+        {
141
+            lock(downloadFiles)
142
+            {
143
+                if (downloadFiles.Count > 0)
144
+                {
145
+                    StartDownload(downloadFiles.Dequeue());
146
+                }
147
+            }
148
+        }
149
+
150
+        /// <summary>
151
+        /// 获取空闲下载器
152
+        /// </summary>
153
+        /// <returns></returns>
154
+        private DownloadRoutine GetLeisureDownloadRoutine()
155
+        {
156
+            return _downloadRoutines.Find(p => p.IsLeisure);
157
+        }
158
+    }
159
+}

+ 11 - 0
DownloadManager.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: d526844b7ba8798409d04a2e12a1a7ec
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: 

+ 155 - 0
DownloadRoutine.cs

@@ -0,0 +1,155 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using System.IO;
5
+using System.Threading.Tasks;
6
+using UnityEngine;
7
+using UnityEngine.Networking;
8
+
9
+namespace TModule.Runtime
10
+{
11
+    public class DownloadRoutine
12
+    {
13
+        /// <summary>
14
+        /// 下载路径
15
+        /// </summary>
16
+        public string DownLoadUrl { get; set; }
17
+
18
+        /// <summary>
19
+        /// 文件保存路径
20
+        /// </summary>
21
+        public string FileSavePath { get; set; }
22
+
23
+        /// <summary>
24
+        /// 是否空闲
25
+        /// </summary>
26
+        public bool IsLeisure { get; set; } = true;
27
+
28
+        /// <summary>
29
+        /// 下载总大小
30
+        /// </summary>
31
+        private long _totalSzie;
32
+
33
+        public long TotalSize => _totalSzie;
34
+
35
+        /// <summary>
36
+        /// 已下载大小
37
+        /// </summary>
38
+        private long _currentDownloadSize;
39
+
40
+        public long CurrentDownloadSize => _currentDownloadSize;
41
+
42
+        //停止下载
43
+        private bool _isStop;
44
+
45
+        public bool IsStop
46
+        {
47
+            get => _isStop ||
48
+#if UNITY_EDITOR 
49
+                !UnityEditor.EditorApplication.isPlaying
50
+
51
+#else
52
+            !Application.isPlaying
53
+#endif
54
+                ;
55
+            set => _isStop = value;
56
+        }
57
+
58
+        public Action onDownloadOver;
59
+
60
+        /// <summary>
61
+        /// 下载中事件 下载进度 总大小 已下载大小
62
+        /// </summary>
63
+        public Action<float,long,long> onProgress;
64
+
65
+        public Action<string> onError;
66
+
67
+        /// <summary>
68
+        /// 开始下载
69
+        /// </summary>
70
+        /// <param name="url"></param>
71
+        /// <returns></returns>
72
+        public async Task StartDownload(string url,string fileSavePath)
73
+        {
74
+            DownLoadUrl = url;
75
+            FileSavePath = fileSavePath;
76
+            IsStop = false;
77
+            _currentDownloadSize = 0;
78
+            IsLeisure = false;
79
+            UnityWebRequest webRequest = UnityWebRequest.Head(DownLoadUrl);
80
+            await webRequest.SendWebRequest();
81
+            if (webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.ProtocolError)
82
+            {
83
+                onError?.Invoke(webRequest.error);
84
+                Debug.Log(webRequest.error); //出现错误 输出错误信息
85
+            }
86
+            else
87
+            {
88
+                string info = webRequest.GetResponseHeader("Content-Length");
89
+                _totalSzie = long.Parse(info);
90
+                await DownloadFile();
91
+            }
92
+        }
93
+
94
+        public void StopDownload()
95
+        {
96
+            IsStop = true;
97
+        }
98
+
99
+        public async Task ContinueDownload()
100
+        {
101
+            if (IsLeisure) return;
102
+            IsStop = false;
103
+            await DownloadFile();
104
+        }
105
+
106
+        async Task DownloadFile()
107
+        {
108
+            string dirPath = Path.GetDirectoryName(FileSavePath);
109
+            if (!Directory.Exists(dirPath))
110
+                Directory.CreateDirectory(dirPath);
111
+            using (FileStream fs = new FileStream(FileSavePath, FileMode.OpenOrCreate, FileAccess.Write,FileShare.ReadWrite))
112
+            {
113
+                _currentDownloadSize = fs.Length;
114
+
115
+                if (_currentDownloadSize < _totalSzie)
116
+                {
117
+                    fs.Seek(_currentDownloadSize, SeekOrigin.Begin);
118
+                    UnityWebRequest request = UnityWebRequest.Get(DownLoadUrl);
119
+                    request.SetRequestHeader("Range", $"bytes={_currentDownloadSize}-");
120
+                    request.SendWebRequest();
121
+                    if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
122
+                    {
123
+                        onError?.Invoke(request.error);
124
+                        Debug.Log(request.error); //出现错误 输出错误信息
125
+                    }
126
+                    else
127
+                    {
128
+                        long index = 0;
129
+                        while (_currentDownloadSize < _totalSzie)
130
+                        {
131
+                            if (IsStop) break;
132
+                            byte[] data = request.downloadHandler.data;
133
+                            if (data != null)
134
+                            {
135
+                                long length = data.Length - index;
136
+                                fs.Write(data, (int)index, (int)length);
137
+                                index += length;
138
+                                _currentDownloadSize += length;
139
+                                onProgress?.Invoke((float)Math.Round((double)_currentDownloadSize / _totalSzie,2), _totalSzie, _currentDownloadSize);
140
+                                if (_currentDownloadSize >= _totalSzie)
141
+                                {
142
+                                    //下载完成
143
+                                    IsLeisure = true;
144
+                                    onDownloadOver?.Invoke();
145
+                                    break;
146
+                                }
147
+                            }
148
+                            await Task.Yield();
149
+                        }
150
+                    }
151
+                }
152
+            }
153
+        }
154
+    }
155
+}

+ 11 - 0
DownloadRoutine.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: ef3321e1cf28b294ea746927f92a0489
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: 

+ 18 - 0
ExtensionAsyncOperation.cs

@@ -0,0 +1,18 @@
1
+using System.Collections;
2
+using System.Collections.Generic;
3
+using System.Runtime.CompilerServices;
4
+using System.Threading.Tasks;
5
+using UnityEngine;
6
+
7
+namespace TModule.Runtime
8
+{
9
+    public static class ExtensionAsyncOperation
10
+    {
11
+        public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
12
+        {
13
+            var tcs = new TaskCompletionSource<object>();
14
+            asyncOp.completed += obj => { tcs.SetResult(null); };
15
+            return ((Task)tcs.Task).GetAwaiter();
16
+        }
17
+    }
18
+}

+ 11 - 0
ExtensionAsyncOperation.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: 9af226bf479be4e4892cbd92f0d26854
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: