Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DownloadHandlerFile and DownloadHandlerScript #8

Open
guizmo01 opened this issue Oct 8, 2018 · 0 comments
Open

DownloadHandlerFile and DownloadHandlerScript #8

guizmo01 opened this issue Oct 8, 2018 · 0 comments

Comments

@guizmo01
Copy link

guizmo01 commented Oct 8, 2018

Would be nice if we could add those new webrequest features.

I have somethin g i did work on in the past, would be nice to hook it up within your wrapper.

` class FileDownloadHandler : DownloadHandlerScript
{
private int expected = -1;
private int received = 0;
private string filepath;
private FileStream fileStream;
private bool canceled = false;

    public FileDownloadHandler(byte[] buffer, string filepath) : base(buffer)
    {
        this.filepath = filepath;
        fileStream = new FileStream(filepath, FileMode.Create, FileAccess.Write);
    }

    protected override byte[] GetData()
    {
        return null;
    }

    protected override bool ReceiveData(byte[] data, int dataLength)
    {
        if (data == null || data.Length < 1)
        {
            return false;
        }

        received += dataLength;

        if (!canceled)
        {
            fileStream.Write(data, 0, dataLength);
        }

        return true;
    }

    protected override float GetProgress()
    {
        if (expected < 0)
        {
            return 0;
        }

        return (float)received / expected;
    }

    protected override void CompleteContent()
    {
        fileStream.Close();
    }

    protected override void ReceiveContentLength(int contentLength)
    {
        expected = contentLength;
    }

    public void Cancel()
    {
        canceled = true;
        fileStream.Close();
        File.Delete(filepath);
    }
}`

`public class Downloader
{
public event Action OnBegin;
public event Action OnComplete;
public event Action OnProgress;
public event Action OnError;

   // public Text bytesText;

    private float progress;

    //public Text response;

    private string cachedfromJson;
  
    public List<UnityWebRequest> requests = new List<UnityWebRequest>();

    private bool needDeleting = false;

    public long ContentLength
    {
        get;
        private set;
    }

    public static string GeneralDevicePath
    {
        get
        {
            string path = Application.persistentDataPath + "/Data/";

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            return path;
        }
    }

    public static string DeviceAssetsPath
    {
        get
        {
            string result = GeneralDevicePath + "Assets/";

            if (!Directory.Exists(result))
            {
                Directory.CreateDirectory(result);
            }

            return result;
        }
    }

    public static string DeviceDatabasePath
    {
        get
        {
            string result = DeviceAssetsPath + "Content/";

            if (!Directory.Exists(result))
            {
                Directory.CreateDirectory(result);
            }

            return result;
        }
    }

    public string CachedValue
    {
        get
        {
            return cachedfromJson;
        }

        set
        {
            cachedfromJson = value;
        }
    }

    public IEnumerator GetAppData(Guid appBuilderId)
    {
        string appBuilderUrlFormat = AppData.ApplicationJSONUrl;

        string jsonUrl = string.Format(appBuilderUrlFormat, appBuilderId);
    
        string jsonPath = string.Format(@"{0}/{1}.json", Application.persistentDataPath, appBuilderId);

        using (UnityWebRequest www = new UnityWebRequest(jsonUrl + "?=" + Guid.NewGuid(), UnityWebRequest.kHttpVerbGET))
        {
            byte[] buffer = new byte[64 * 1024];

            www.SetRequestHeader("Cache-Control", "max-age=0, no-cache, no-store");
            www.SetRequestHeader("Pragma", "no-cache");

            www.downloadHandler = new FileDownloadHandler(buffer, jsonPath);

            www.SendWebRequest();

            while (!www.isDone)
            {
                yield return www;
            }

            if (www.isNetworkError || www.isHttpError)
            {
                long responseCode = www.responseCode;

                Debug.Log(string.Format("request {0} error {1}", jsonUrl, www.error));
                //response.text = www.error + " Error Code: " + responseCode.ToString();
            }
            else
            {
                www.downloadHandler.Dispose();
            }
        }

        var jsonContent = File.ReadAllText(jsonPath);
        var appData = JsonUtility.FromJson<T>(jsonContent);
      
        if (OnBegin != null)
        {
            OnBegin(appData);
        }
    }

    public void Loop(object obj, Guid id)
    {
        var fields = obj.GetType().GetFields();

        string val = "https://jlltest.vvhosting.co.uk/api/Floorplans" + id + "/";

        foreach (FieldInfo field in fields)
        {
            var value = field.GetValue(obj);

            //
            // TODO Check "?cache=" value, if changed => download (update) the file, if not => ignore the file
            //
            if (value.ToString().StartsWith("!uploads"))
            {
                string a = value.ToString();

                cachedfromJson = string.Empty;

                if (!string.IsNullOrEmpty(a))
                {
                    cachedfromJson = a.Split('?')[1];
                }

                if (value.ToString().Contains(".jpg"))
                 {
                    StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".jpg", "FloorPlans"));
                 }

                if (value.ToString().Contains(".mp3"))
                 {
                    StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".mp3", "Audio"));
                 }

                 if (value.ToString().Contains(".mp4"))
                 {
                     StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".mp4", "Video"));
                 }

                if (value.ToString().Contains(".png"))
                {     
                   StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".png", "PNGImages"));
                }

                if (value.ToString().Contains(".jpg"))
                {
                    StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".jpg", "JPGImages"));   
                }

                if (value.ToString().Contains(".pdf"))
                 {
                     StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".pdf", "PDF"));
                 }
            }

            if (field.FieldType != typeof(string))
            {
                Loop(value, id);
            }

            //
            // It's collection, loop through items
            //
            if (typeof(IList).IsAssignableFrom(field.FieldType))
            {
                foreach (var v in value as IList)
                {
                    Loop(v, id);
                }
            }
        }
    }

    // Not sure how to use this to be honest
    public IEnumerator CheckFileSize(string url, string filePath)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Head(url))
        {
            yield return webRequest.SendWebRequest();

            if (webRequest.GetResponseHeaders() == null)
            {
                Debug.LogError("response header is null");
            }
            else
            {
                //webRequest.GetResponseHeader("Content-Length");
                Debug.Log(webRequest.GetResponseHeader("Content-Length"));

                var fileInfo = new FileInfo(filePath);

                Debug.Log("The size of the file is = " + fileInfo.Length);

                yield return new WaitForEndOfFrame();

                if (fileInfo.Length.ToString() != webRequest.GetResponseHeader("Content-Length"))
                {
                    Debug.Log("File isn't the same size so delete it and start download again");
                    File.Delete(filePath);
                    yield return new WaitForEndOfFrame();

                    needDeleting = true;
                }
            }
        }
    }

    string ResponseToString(byte[] data)
    {
        //byte data to UTF8 encoding string
        return System.Text.Encoding.UTF8.GetString(data);
    }

    // Method that downloads a file
    public IEnumerator DownloadFiles(string url, string file, string folderStructure = "")
    {
        using (UnityWebRequest www = new UnityWebRequest(url))
        {
            byte[] buffer = new byte[256 * 1024];

            www.SetRequestHeader("Cache-Control", "max-age=0, no-cache, no-store");
            www.SetRequestHeader("Pragma", "no-cache");

            www.chunkedTransfer = false;

            string path;

            if (folderStructure == "")
            {
                path = Path.Combine(DeviceDatabasePath, file);
            }
            else
            {
                path = Path.Combine(DeviceDatabasePath + folderStructure, file);
            }

            if (!Directory.Exists(Path.GetDirectoryName(path)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(path));
            }

            // Download file if it does not exist
            if (!File.Exists(path))
            {
                yield return FireWebRequest(buffer, path, url, www);
            }
            else
            {
                yield return CheckFileSize(url, path);

                if (needDeleting == true)
                {
                    yield return FireWebRequest(buffer, path, url, www);
                    needDeleting = false;
                }
            }
        }
    }

    private IEnumerator FireWebRequest(byte[] buffer, string path, string url, UnityWebRequest www)
    {
        www.downloadHandler = new FileDownloadHandler(buffer, path);

        requests.Add(www);

        www.timeout = 1000;

        www.SendWebRequest();

        Debug.Log("You are now here");

        yield return DownloadProgress(www);

        // Check for errors
        if (www.isNetworkError || www.isHttpError)
        {
            long responseCode = www.responseCode;

            Debug.Log(string.Format("request {0} error {1}", url, www.error + " " + responseCode.ToString()));

            if (www.timeout >= 1000)
            {
                response.text = www.error + " Error Code: " + "504";
            }
            else
            {
                response.text = www.error + " Error Code: " + responseCode.ToString();
            }

            requests.Remove(www);

            www.Abort();

            if (OnError != null)
            {
                OnError(responseCode);
            }
        }
        else
        {
            // File have been downloaded
            Debug.Log("File successfully downloaded and saved to " + path);

            if (OnComplete != null)
            {
                OnComplete();
            }

            www.downloadHandler.Dispose();

            requests.Remove(www);

            buffer = null;
        }
    }

    // Download progress bar and text
    public IEnumerator DownloadProgress(UnityWebRequest uwr)
    {
        while (!uwr.isDone)
        {
            progress = uwr.downloadProgress;

            if (Application.internetReachability == NetworkReachability.NotReachable)
            {
                Debug.Log("Internet connection lost " + uwr.responseCode);

                response.text = "Internet connection has been lost" + " Error Code: " + "503";
            }
            else
            {
               response.text = string.Empty;
               bytesText.text = string.Format("{0} MB", (uwr.downloadedBytes / 1000000)).ToString();
            }

            if (OnProgress != null)
            {
                Debug.Log("OnProgess event not null");
                OnProgress(progress);
            }

            yield return null;
        }
    }
}`

Obviously it would need some refactoring to implement within your wrapper But the way this downloader works, is check if file already exist or not, if it doesn't, it downloads it, if it exist it checks for the size of the file from server and then checks file size from persistent path if it doesn't match delete the file from path and re-download it from server, the reason i had to do this is if the app would crash of closed during download, there was no way for me to resume the download when restarting the app.

The Loop method is recursive and uses reflection, we can use this if we want to dynamically download all the available files at once without having to iterate through the json structure multiple time. It find any properties that contains the file url (providing the server is setup to have a specific suffix for each file).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant