123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using BestHTTP;
- namespace BestHTTP.Examples
- {
- public sealed class LargeFileDownloadSample : MonoBehaviour
- {
- /// <summary>
- /// The url of the resource to download
- /// </summary>
- const string URL = "http://uk3.testmy.net/dl-102400";
- #region Private Fields
- /// <summary>
- /// Cached request to be able to abort it
- /// </summary>
- HTTPRequest request;
- /// <summary>
- /// Debug status of the request
- /// </summary>
- string status = string.Empty;
- /// <summary>
- /// Download(processing) progress. Its range is between [0..1]
- /// </summary>
- float progress;
- /// <summary>
- /// The fragment size that we will set to the request
- /// </summary>
- int fragmentSize = HTTPResponse.MinBufferSize;
- #endregion
- #region Unity Events
- void Awake()
- {
- // If we have a non-finished download, set the progress to the value where we left it
- if (PlayerPrefs.HasKey("DownloadLength"))
- progress = PlayerPrefs.GetInt("DownloadProgress") / (float)PlayerPrefs.GetInt("DownloadLength");
- }
- void OnDestroy()
- {
- // Stop the download if we are leaving this example
- if (request != null && request.State < HTTPRequestStates.Finished)
- {
- request.OnProgress = null;
- request.Callback = null;
- request.Abort();
- }
- }
- void OnGUI()
- {
- GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
- {
- // Draw the current status
- GUILayout.Label("Request status: " + status);
- GUILayout.Space(5);
- // Draw the current progress
- GUILayout.Label(string.Format("Progress: {0:P2} of {1:N0}Mb", progress, PlayerPrefs.GetInt("DownloadLength") / 1048576 /*1 Mb*/));
- GUILayout.HorizontalSlider(progress, 0, 1);
- GUILayout.Space(50);
- if (request == null)
- {
- // Draw a slider to be able to change the fragment size
- GUILayout.Label(string.Format("Desired Fragment Size: {0:N} KBytes", fragmentSize / 1024f));
- fragmentSize = (int)GUILayout.HorizontalSlider(fragmentSize, HTTPResponse.MinBufferSize, 10 * 1024 * 1024);
- GUILayout.Space(5);
- string buttonStr = PlayerPrefs.HasKey("DownloadProgress") ? "Continue Download" : "Start Download";
- if (GUILayout.Button(buttonStr))
- StreamLargeFileTest();
- }
- else if (request.State == HTTPRequestStates.Processing && GUILayout.Button("Abort Download"))
- {
- // Simulate a connection lost
- request.Abort();
- }
- });
- }
- #endregion
- #region Private Helper Functions
- // Calling this function again when the "DownloadProgress" key in the PlayerPrefs present will
- // continue the download
- void StreamLargeFileTest()
- {
- request = new HTTPRequest(new Uri(URL), (req, resp) =>
- {
- switch (req.State)
- {
- // The request is currently processed. With UseStreaming == true, we can get the streamed fragments here
- case HTTPRequestStates.Processing:
- // Set the DownloadLength, so we can display the progress
- if (!PlayerPrefs.HasKey("DownloadLength"))
- {
- string value = resp.GetFirstHeaderValue("content-length");
- if (!string.IsNullOrEmpty(value))
- PlayerPrefs.SetInt("DownloadLength", int.Parse(value));
- }
- // Get the fragments, and save them
- ProcessFragments(resp.GetStreamedFragments());
- status = "Processing";
- break;
- // The request finished without any problem.
- case HTTPRequestStates.Finished:
- if (resp.IsSuccess)
- {
- // Save any remaining fragments
- ProcessFragments(resp.GetStreamedFragments());
- // Completely finished
- if (resp.IsStreamingFinished)
- {
- status = "Streaming finished!";
- // We are done, delete the progress key
- PlayerPrefs.DeleteKey("DownloadProgress");
- PlayerPrefs.Save();
- request = null;
- }
- else
- status = "Processing";
- }
- else
- {
- status = string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
- resp.StatusCode,
- resp.Message,
- resp.DataAsText);
- Debug.LogWarning(status);
- request = null;
- }
- break;
- // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
- case HTTPRequestStates.Error:
- status = "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception");
- Debug.LogError(status);
- request = null;
- break;
- // The request aborted, initiated by the user.
- case HTTPRequestStates.Aborted:
- status = "Request Aborted!";
- Debug.LogWarning(status);
- request = null;
- break;
- // Connecting to the server is timed out.
- case HTTPRequestStates.ConnectionTimedOut:
- status = "Connection Timed Out!";
- Debug.LogError(status);
- request = null;
- break;
- // The request didn't finished in the given time.
- case HTTPRequestStates.TimedOut:
- status = "Processing the request Timed Out!";
- Debug.LogError(status);
- request = null;
- break;
- }
- });
- // Are there any progress, that we can continue?
- if (PlayerPrefs.HasKey("DownloadProgress"))
- // Set the range header
- request.SetRangeHeader(PlayerPrefs.GetInt("DownloadProgress"));
- else
- // This is a new request
- PlayerPrefs.SetInt("DownloadProgress", 0);
- #if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR)
- // If we are writing our own file set it true(disable), so don't duplicate it on the file-system
- request.DisableCache = true;
- #endif
- // We want to access the downloaded bytes while we are still downloading
- request.UseStreaming = true;
- // Set a reasonable high fragment size. Here it is 5 megabytes.
- request.StreamFragmentSize = fragmentSize;
- // Start Processing the request
- request.Send();
- }
- /// <summary>
- /// In this function we can do whatever we want with the downloaded bytes. In this sample we will do nothing, just set the metadata to display progress.
- /// </summary>
- void ProcessFragments(List<byte[]> fragments)
- {
- if (fragments != null && fragments.Count > 0)
- {
- /*string dir = "TODO!";
- string filename = "TODO!";
- using (System.IO.FileStream fs = new System.IO.FileStream(System.IO.Path.Combine(dir, filename), System.IO.FileMode.Append))
- for (int i = 0; i < fragments.Count; ++i)
- fs.Write(fragments[i], 0, fragments[i].Length);*/
- for (int i = 0; i < fragments.Count; ++i)
- {
- // Save how many bytes we wrote successfully
- int downloaded = PlayerPrefs.GetInt("DownloadProgress") + fragments[i].Length;
- PlayerPrefs.SetInt("DownloadProgress", downloaded);
- }
- PlayerPrefs.Save();
- // Set the progress to the actually processed bytes
- progress = PlayerPrefs.GetInt("DownloadProgress") / (float)PlayerPrefs.GetInt("DownloadLength");
- }
- }
- #endregion
- }
- }
|