I am working on a weekend project that aggregates downloads from other sites in a zip file with Blazor (webassmbly).
The zip file is created in c# code and need to be saved on the local computer. I am using a modified version of this answer because the file size can easily extend over 400 mb.
My Version partitions the js call to not imminently overflow the webassembly VM but after a certain filesize it happens and i get the folloring exception:
WASM: Try saving 213776418bytes --my message
blazor.webassembly.js:1 WASM: GC_MAJOR_SWEEP: major size: 1808K in use: 94964K
blazor.webassembly.js:1 WASM: GC_MAJOR: (LOS overflow) time 71.98ms, stw 72.00ms los size: 486832K in use: 481083K
WASM: Error: Garbage collector could not allocate 16384 bytes of memory for major heap section.
Uncaught (in promise) ExitStatus {name: "ExitStatus", message: "Program terminated with exit(1)", status: 1}
Is there currently any other way to save a file from WebAssembly other then transferring the file content to js and then save them with Blob?
I found a solution. With the latest update to .Net5 it is now possible to use the IJSUnmarshalledRuntime
. This makes everything a lot easier. Beware there seems to be still limits or other restrictions in place I was forced to partition my files to around 200mb but the solution is very fast and does seem to work "fine" enough. Warning: Works only in Webassembly Blazor!
First write use a FileUtil:
public static class FileUtil
{
public static void SaveAs(this IJSRuntime js, string filename, MemoryStream data)
{
var rt = js as IJSUnmarshalledRuntime;
var dataArray = data.ToArray();
rt.InvokeUnmarshalled<string, byte[], object>(
"saveAsFile",
filename,
dataArray);
}
}
and then use this js function:
function saveAsFile(filenamePointer, contentPointer) {
var parts = Blazor.platform.toUint8Array(contentPointer);
var filename = BINDING.conv_string(filenamePointer);
var blob = new Blob([parts], { type: "application/octet-stream" });
if (navigator.msSaveBlob) {
//Download document in Edge browser
navigator.msSaveBlob(blob, filename);
}
else {
var link = document.createElement('a');
link.download = filename;
link.href = URL.createObjectURL(blob);
document.body.appendChild(link); // Needed for Firefox
link.click();
document.body.removeChild(link);
}
}