Closed fixnil closed 2 years ago
Hi @fixnil, 😊 Thanks for the issue.
This is related to issue #10 which is closed; you can read more about it there.
As mentioned in the first response to that issue the File System Access API doesn't give a way to read a file as a Uint8Array.
A Blob can be read as an ArrayBuffer but that is not directly convertible to a byte array
. So to do this you would need to call a JS method through JSInterop and go through a couple of steps as described in the last comment of that thread.
In release 1.1.0 I added the possibility to stream to a FileSystemWritableFileStream by having it extend Stream
that has writing
enabled.
I would like it to be possible to do the same for Blob in order to be able to stream from it by again extending Stream
with reading
enabled.
I am unsure whether this is inside this library's intended scope as it is a lot of work with the JS Blob which is a part of the File API. A full wrapper of the File API should probably be its own library so that it can be used by other libraries/projects that would use that functionality without depending on this library.
I am leaving this issue open so that I can track interest in solving this. I haven't decided whether or not this should be a part of this library or potentially spun out to its own library (Blazor.File
) that this library (Blazor.FileSystemAccess
) could reference.
I have noted a couple of libraries that also work with JSInterop and Files which might be a help for future work.
Sorry, I forgot to check those closed issues.
Your solution works perfectly, my code is as follows:
file.js
export async function arrayBuffer(blob) {
var buffer = await blob.arrayBuffer();
var bytes = new Uint8Array(buffer);
return bytes;
}
Index.razor
var file = await _handle.GetFileAsync();
var module = await this.JSRuntime.InvokeAsync<IJSObjectReference>("import", "./file.js");
var bytes = await module.InvokeAsync<byte[]>("arrayBuffer", file.JSReference);
await System.IO.File.WriteAllBytesAsync(Filename, bytes);
I don't know if I need to submit a PR as an alternative, before the official File API goes live? The code looks like this:
Blazor.FileSystemAccess/src/KristofferStrube.Blazor.FileSystemAccess/Blob/Blob.cs
// ...
public class Blob
{
// ...
public async Task<byte[]> ArrayBufferAsync()
{
return await helper.InvokeAsync<byte[]>("arrayBuffer", JSReference);
}
}
By the way, I'll mention a small problem I found while using it.
As you can see the code above, I had to use the fully qualified name because of the conflict.
await System.IO.File.WriteAllBytesAsync(Filename, bytes);
Is there a better solution here? Or is there another issue that needs to be created to discuss this.
Hey @fixnil,
Sounds good. You can create a PR with the solution if you want. I think it is pretty nice. If you add it to the existing helper js file and add the method to the Blob
class as you described then that would be awesome.
If you submit a PR. Then I would like you to also create an example use case and add that to the demo on a new page. I imagine that use cases are related to loading binary files that have some specific encoding. If you can't figure out a demo then I can also help with that once you have a PR out.
Regarding your problem with having to use the full namespace then I can recommend to either use using static System.IO.File
or adding an alias for it using SIOF = System.IO.File
.
And once we have a PR for this issue we can close it and I can create a new issue specifically for having Blob
extend Stream
and consider whether we want that in that issue.
Hi @KristofferStrube,
I've added the method to the blob and added a simple case to prove it works, please review the code if you have time.
Thanks.
Hi @KristofferStrube, I've recently had some issues reading non-text files into the browser.
Expect an API like this:
or like this:
Thank you for your work!