In Unity3d Webgl I download and write big file (about 100 mb and more) to cache (indexeddb).
I downloaded file with UnityWebRequest
and write file in downloadHandler.
Sometimes after call filestream.Write()
or filestream.Flush()
Chrome will crash.
Exception not available, only crash tab of chrome. Crash happens abount in 50 percent of dowloads.
public class Downloader : MonoBehaviour
{
public IEnumerator DownloadFileCoroutine(string url, string filePath, string clientName, int fileId, Action<int> downloadedCallback)
{
var currentWebRequest = UnityWebRequest.Get(url);
currentWebRequest.downloadHandler = new ToFileDownloadHandler(new byte[64 * 1024], filePath);
var downloadHendler = (currentWebRequest.downloadHandler as ToFileDownloadHandler);
currentWebRequest.Send();
while (!currentWebRequest.isDone && !currentWebRequest.isNetworkError && !currentWebRequest.isHttpError)
{
if (currentWebRequest.isNetworkError)
{
yield break;
}
}
if (currentWebRequest.isNetworkError)
{
downloadHendler.Cancel();
}
else
{
/// suceess
}
}
public class ToFileDownloadHandler : DownloadHandlerScript
{
private int _expected = -1;
private long _received = 0;
private readonly string _filepath;
private readonly FileStream _fileStream = null;
private bool _canceled = false;
public ToFileDownloadHandler(byte[] buffer, string filepath) : base(buffer)
{
CreateDir();
_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);
_fileStream.Flush();
}
return true;
}
protected override float GetProgress()
{
if (_expected < 0) return 0;
return (float)_received / _expected;
}
protected override void CompleteContent()
{
_fileStream.Close();
_isComplete = true;
}
protected override void ReceiveContentLength(int contentLength)
{
_expected = contentLength;
}
public void Cancel()
{
if (_canceled) return;
_canceled = true;
if (_fileStream != null)
{
_fileStream.Close();
}
File.Delete(_filepath);
}
private void CreateDir()
{
cachePath = Application.persistentDataPath;
if (!Directory.Exists(cachePath))
{
Directory.CreateDirectory(cachePath);
}
}
}
}