1. 程式人生 > >unity資源下載實現斷點下載

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

;         FileStream fs = null;                        //如果有臨時檔案   讀取臨時檔案的長度 並移動檔案流指標         if (File.Exists(tempFile))         {             fs = File.OpenWrite(tempFile);             startPos = fs.Length;             fs.Seek(startPos, SeekOrigin.Current); //移動檔案流中的當前指標         }         else         {             //獲取檔案或目錄的路徑             string direName = Path.GetDirectoryName(tempFile);             //如果沒有這個根路徑  就建立             if (!Directory.Exists(direName))             {                 Directory.CreateDirectory(direName);             }             fs = new FileStream(tempFile, FileMode.Create);         }

      //我這個斷點續傳  下載資源  使用一個協程下載的,可能同時開啟不止一個這個協程,因為協程可能隨時停止,開啟的檔案流沒有

       //關閉,那麼下次就無法訪問這個檔案;防止這種情況出現,我就用一個字典記錄每次開啟的檔案流,當協程終端時,手動關閉打

      //開的   所有檔案流         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());             }         }     }