Skip to content

Instantly share code, notes, and snippets.

@ReGaSLZR
Created April 21, 2023 05:40
Show Gist options
  • Save ReGaSLZR/7a58ae79f271fdc5cbab40ab8d5c4e81 to your computer and use it in GitHub Desktop.
Save ReGaSLZR/7a58ae79f271fdc5cbab40ab8d5c4e81 to your computer and use it in GitHub Desktop.
A normal Unity script (class) that contains helper codes for checking, downloading and saving files locally.
using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace ReGaSLZR.IO
{
/// <summary>
/// FileHelper.cs
///
/// A normal class that contains helper codes for
/// checking, downloading and saving files locally.
/// Operation uses a Unity Coroutine and so lives on the Main Thread.
/// Just create an instance of this and you can use it immediately.
///
/// <author>Renelie G. Salazar</author>
/// </summary>
public class FileHelper
{
public const string SAVE_PATH = "/VideoLibrary/";
#region Client Impl
private bool IsFileAvailableLocally(string path) => File.Exists(path);
private string GetSavePath(string filename)
{
string tempPath;
#if UNITY_EDITOR
tempPath = Application.dataPath;
#else
tempPath = Application.persistentDataPath;
#endif
tempPath += SAVE_PATH;
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
return tempPath + filename;
}
private void SaveFile(string fullPath, byte[] fileDownloaded)
=> File.WriteAllBytes(fullPath, fileDownloaded);
private IEnumerator C_DownloadFile(string url, string fullLocalPath,
Action<string> onSuccess, Action onFailure)
{
UnityWebRequest www = UnityWebRequest.Get(url);
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.ConnectionError)
{
onFailure?.Invoke();
}
else
{
SaveFile(fullLocalPath, www.downloadHandler.data);
onSuccess?.Invoke(fullLocalPath);
}
}
#endregion //Client Impl
#region Public API
/// <summary>
/// Checks if the file is already stored locally.
/// If so, the full local path is returned to the caller.
/// If not, the file is downloaded and stored locally, then returned to the caller.
/// </summary>
public void DownloadFileToLocal(MonoBehaviour caller, string url, string fileName,
Action<string> onSuccess, Action onFailure)
{
var fullLocalPath = GetSavePath(fileName);
if (!IsFileAvailableLocally(fullLocalPath))
{
caller.StartCoroutine(C_DownloadFile(
url, fullLocalPath, onSuccess, onFailure));
}
else
{
onSuccess?.Invoke(fullLocalPath);
}
}
#endregion //Public API
} //end of class
} //end of namespace
@ReGaSLZR
Copy link
Author

ReGaSLZR commented Apr 21, 2023

Sample usage:

        private VideoPlayer videoPlayer;
        private FileHelper fileHelper = new FileHelper();

        private void LoadVideo()
        {
            var someUri = "https://www.somesite.com/";
            Uri baseUri = new Uri(someUri);
            var fileName = "file_name_of_the_video" + ".mp4";
            var url = new Uri(baseUri, (UnityWebRequest.EscapeURL(fileName))).ToString();

            fileHelper.DownloadFileToLocal(this, url, fileName, 
                OnSuccessLoadingVideo, OnFailureLoadingVideo);
        }

        private void OnSuccessLoadingVideo(string fullLocalVideoPath)
        {
            videoPlayer.source = VideoSource.Url;
            videoPlayer.url = fullLocalVideoPath;

            Debug.Log(videoPlayer.url);

            videoPlayer.Play();
            Debug.Log("Playing: " + name);
        }

        private void OnFailureLoadingVideo()
        {
            Debug.LogWarning($"Failed to load video: {name}");
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment