unity資源下載實現斷點下載
以下是我們專案中實際應用的斷點續傳程式碼
public IEnumerator downloadByHttpRequest(string url,int id,string assetbundlename,GameObject slider,GameObject NoDown,GameObject BlueTop) { //臨時檔名(把下載的資源的名字修改為臨時名字 ) string assetbundletempname = assetbundlename.Replace(".assetbundle", "temp.assetbundle"); //開啟上次下載的檔案 long startPos = 0; //臨時檔案路勁(臨時儲存的絕對路徑) string tempFile = LoadLocalResources.instance.GetSaveAssetBundlePath() +"/"+ assetbundletempname
//我這個斷點續傳 下載資源 使用一個協程下載的,可能同時開啟不止一個這個協程,因為協程可能隨時停止,開啟的檔案流沒有
//關閉,那麼下次就無法訪問這個檔案;防止這種情況出現,我就用一個字典記錄每次開啟的檔案流,當協程終端時,手動關閉打
//開的 所有檔案流 if (fsDic.ContainsKey(id)) { fsDic[id] = fs; } else { fsDic.Add(id, fs); } //每點選一次 動態設定 連結限制 (儘量設大點,不然莫名其妙連結超時) System.Net.ServicePointManager.DefaultConnectionLimit = CoroutineController.Instance.LoadingDic.Count * 3 + 50;
//首先獲取下載長度進行比較 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; request.ReadWriteTimeout = ReadWriteTimeOut; request.Timeout = TimeOutWait; long total = request.GetResponse().ContentLength; //當前已下載檔案長度 long curSize = startPos; //如果已下載長度等於 總長度 儲存檔案 if (curSize == total) { fs.Flush(); fs.Close(); fs = null; fsDic.Remove(id);
//如果下載完成 把臨時檔案變成正式檔案 File.Move(tempFile, LoadLocalResources.instance.GetSaveAssetBundlePath() + "/" + assetbundlename); //下面的邏輯是我們專案中的邏輯 if (File.Exists(LoadLocalResources.instance.GetSaveAssetBundlePath() + "/" + assetbundlename)) { //刪除儲存 //PlayerPrefs.DeleteKey("OpusId" + id); //LoadingDic.Remove(id.ToString()); //本地邏輯轉換 if (slider != null) { slider.SetActive(false); } if (NoDown != null) { NoDown.SetActive(false); } if (BlueTop != null) { BlueTop.SetActive(true); } } } else {
//如果存在臨時檔案 設定HttpWebRequest請求資源的Range 第二次請求下載 request = WebRequest.Create(url) as HttpWebRequest; request.ReadWriteTimeout = ReadWriteTimeOut; request.Timeout = TimeOutWait; if (startPos > 0) { //設定Range值,斷點續傳 request.AddRange((int)startPos); } //向伺服器請求,獲得伺服器迴應資料流 WebResponse respone = request.GetResponse(); Stream ns = respone.GetResponseStream(); //下載檔案總長度 long totalSize = respone.ContentLength; //設定每次讀取位元組流的長度 byte[] bytes = new byte[oneReadLen]; int readSize = ns.Read(bytes, 0, oneReadLen); // 讀取第一份資料 while (readSize > 0) { fs.Write(bytes, 0, readSize); // 將下載到的資料寫入臨時檔案 curSize += readSize; // 判斷是否下載完成 // 下載完成將temp檔案,改成正式檔案 if (curSize == totalSize) { fs.Flush(); fs.Close(); fs = null; fsDic.Remove(id);
//下載完成 把臨時檔案替換成正式檔案 File.Move(tempFile, LoadLocalResources.instance.GetSaveAssetBundlePath() + "/" + assetbundlename); //確保轉換結束 if (File.Exists(LoadLocalResources.instance.GetSaveAssetBundlePath() + "/" + assetbundlename)) { //刪除儲存 // PlayerPrefs.DeleteKey("OpusId" + id); // LoadingDic.Remove(id.ToString()); //本地邏輯轉換 if (slider != null) { slider.SetActive(false); } if (NoDown != null) { NoDown.SetActive(false); } if (BlueTop != null) { BlueTop.SetActive(true); } } } // 往下繼續讀取 readSize = ns.Read(bytes, 0, oneReadLen); yield return null; //下載進度計算 float progress = (float)curSize / (float)totalSize; if (!LoadingDic.ContainsKey(id.ToString())) { LoadingDic.Add(id.ToString(), null); } PlayerPrefs.SetString("OpusId" + id, progress.ToString()); } } }