Upload bundles to ftp server with Filezilla (transfer type is set to be binary)
-Download bundles with UnityWebRequest, save them to device Application.persistentDataPath:
IEnumerator downloadAssetBundles(string[] names)
{
foreach (string name in names)
{
sceneBundleURL += name;
UnityWebRequest www = new UnityWebRequest ();
www = UnityWebRequest.Get(sceneBundleURL);
www.downloadHandler = new UnityEngine.Networking.DownloadHandlerBuffer();
www.Send();
while (!www.isDone)
{
yield return null;
}
if (www.isNetworkError)
{
Debug.Log (www.responseCode);
}
else
{
string filePath = System.IO.Path.Combine(Application.persistentDataPath, name.ToString ());
Debug.Log ("saving to ******: "+filePath);
System.IO.FileStream cache = new System.IO.FileStream(filePath, System.IO.FileMode.Create);
cache.Write(www.downloadHandler.data, 0, www.downloadHandler.data.Length);
cache.Close();
UnityEngine.iOS.Device.SetNoBackupFlag(filePath);
www.Dispose ();
}
}
yield return new WaitForSeconds (0.5f);
}
-When I load the bundle from file as following, I get error as:
Error while downloading Asset Bundle: Failed to decompress data for the AssetBundle ‘file:///var/mobile/Containers/Data/Application/D2C8E6CE-5D08-4735-A701-9C9969025FDE/Documents/leveldata.level’.
Not familiar with System.IO.FileStream but check if it needs to be opened in binary mode instead of text mode on Windows, if that’s your OS.
ALSO, when you go to read it in, check the byte count compared to the length when you wrote it to disk, and also compare that to the length of the created asset, see if there are any differences. Needs to be byte-exact obviously.
I tried File.WriteAllBytes as well also I can see that file is being downloaded with appropriate size and saved to Application.persistentDataPath, however the problem is with loading them.
Im sure I do build with IOS target and I can load the same AssetBundles from StreamingAssets folder inside the project also if I load from FTP URL it works too, so Im doing something wrong while saving them. I iterate multiple assets download and save individually, would it be a problem?
I want to make my own mechanism that downloads the bundles to Application.persistentDataPath and loads assets from there.
Bundle names are stored in an XML file, so before any download I read the bundle names to an array then iterate a foreach loop that creates a UnityWebRequest then dispose the request.
The problem seems right there because I was downloading and saving an individual file “leveldata.level” to Application.persistentDataPath and able to get assetbundle in another scene. However, when I download multiple assets, something gets broken…
Everything you’re doing seems reasonable, and if the byte count is the same, the only next thing I can think of is to do something like a CRC check, or even a byte-for-byte check on a copy of the data that you put in Streaming Assets and see how it differs from the one over the wire. To do this you’d have to use the downloader handler again to get it out of persistent data.
Also, are you able to read the copy that you put into Streaming assets, write that data to persistent data, THEN open it from persistent data as an asset bundle?
Thank you Kurt for the help, I tried the variations you have been commenting and found that byte-for-byte check worked. Now it is working as I was willing for. It seems that the coroutine was being interrupted before the download finishes therefore I had missing binary file…
That’s another thing to check: the download manager interface might operate in “block mode,” whereby it only gives you pieces at a time. For smaller files that means all of it, but for larger files it might require multiple iterations. I’m not that familiar with the new UnityWebRequest system and all of its downloading nuances, but given that it’s impossible to download a 1gb block all at once (you can’t allocate that much RAM), it’s likely they support block-by-block transfer too.
That is correct, it is block wise. New UnityWebRequest system is missing lots of information, there should be more use cases provided. Now facing the problem with large data, somehow download interrupts. I think the best way would be to check the size of the file and iterate over it, that is the initial solution I had unless there is another function from the API…
I had the same issue. In my scenario it seems like FileZilla was the culprit: When uploading the asset bundle with FileZilla the bundle got bad. When using Transmit, the same bundle worked perfectly fine.