I want to have a SPA that's doing all the work client side and even generating some graphs/visuals.
I'd like to be able to have the user click buttons and save the visuals, tables, and other things from the page (that are both seen and not seen, so right click save or copy/paste is not always an option).
How do I call a function from the webassembly/blazor library, get it's results and save it as a file on the client side?
the idea is something like this...?
cshtml
<input type="file" onchange="@ReadFile">
<input type="file" onchange="@SaveFile">
@functions{
object blazorObject = new blazorLibrary.SomeObject();
void ReadFile(){
blazorObject.someFunction(...selectedFile?...);
}
void SaveFile(){
saveFile(...selectedFile..?)
}
}
Creator of Blazor Steve Sanderson used JavaScript interop for similar task during one of his last presentations.
You can find example on BlazorExcelSpreadsheet
Solution includes three parts:
1) JavaScript
function saveAsFile(filename, bytesBase64) {
var link = document.createElement('a');
link.download = filename;
link.href = "data:application/octet-stream;base64," + bytesBase64;
document.body.appendChild(link); // Needed for Firefox
link.click();
document.body.removeChild(link);
}
2) C# interop wrapper
public static class FileUtil
{
public async static Task SaveAs(IJSRuntime js, string filename, byte[] data)
{
await js.InvokeAsync<object>(
"saveAsFile",
filename,
Convert.ToBase64String(data));
}
}
3) Call from your component
@inject IJSRuntime js
@functions {
void DownloadFile() {
var text = "Hello, world!";
var bytes = System.Text.Encoding.UTF8.GetBytes(text);
FileUtil.SaveAs(js, "HelloWorld.txt", bytes);
}
}
You can see it an action in Blazor Fiddle