// Requires UniTask support
#if TFLITE_UNITASK_ENABLED
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;
using Cysharp.Threading.Tasks;
namespace TensorFlowLite
{
///
/// Simple remote file download and cache system.
/// Not for production use.
///
[Serializable]
public class RemoteFile : IProgress
{
public enum DownloadLocation
{
Persistent,
Cache,
}
public string url;
public DownloadLocation downloadLocation = DownloadLocation.Persistent;
public event Action OnDownloadProgress;
public string LocalPath
{
get
{
string dir = downloadLocation switch
{
DownloadLocation.Persistent => Application.persistentDataPath,
DownloadLocation.Cache => Application.temporaryCachePath,
_ => throw new Exception($"Unknown download location {downloadLocation}"),
};
// make hash from url
string ext = GetExtension(url);
string fileName = $"{url.GetHashCode():X8}{ext}";
return Path.Combine(dir, fileName);
}
}
public bool HasCache => File.Exists(LocalPath);
public RemoteFile() { }
public RemoteFile(string url, DownloadLocation location = DownloadLocation.Persistent)
{
this.url = url;
downloadLocation = location;
}
// IProgress
public void Report(float value)
{
OnDownloadProgress?.Invoke(value);
}
public async UniTask Load(CancellationToken cancellationToken)
{
string localPath = LocalPath;
if (HasCache)
{
Log($"Cache Loading file from local: {localPath}");
using var handler = new DownloadHandlerBuffer();
if (!localPath.StartsWith("file:/"))
{
localPath = $"file://{localPath}";
}
using var request = new UnityWebRequest(localPath, "GET", handler, null);
this.Report(0.0f);
await request.SendWebRequest().ToUniTask(progress: this, cancellationToken: cancellationToken);
this.Report(1.0f);
return handler.data;
}
else
{
Log($"Cache not found at {localPath}. Loading from: {url}");
using var handler = new DownloadHandlerFile(localPath);
handler.removeFileOnAbort = true;
using var request = new UnityWebRequest(url, "GET", handler, null);
this.Report(0.0f);
await request.SendWebRequest().ToUniTask(progress: this, cancellationToken: cancellationToken);
this.Report(1.0f);
return await File.ReadAllBytesAsync(localPath, cancellationToken);
}
}
static string GetExtension(string url)
{
string ext = Path.GetExtension(url);
if (ext.Contains('?'))
{
ext = ext[..ext.IndexOf('?')];
}
return ext;
}
[Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
static void Log(string message)
{
UnityEngine.Debug.Log(message);
}
}
}
#endif // TFLITE_UNITASK_ENABLED