GithubHelp home page GithubHelp logo

Comments (4)

EricNgo1972 avatar EricNgo1972 commented on July 23, 2024 1

Adding MaximumReceivemessageSize option indeed resolved the limitation. Thanks.

from blazor.filesystemaccess.

KristofferStrube avatar KristofferStrube commented on July 23, 2024

You may be using it in a Blazor Server App or a Blazor Web App project from the exception I see you get. Is that correct?

As I note in the project README under the Usage Section:

The package can be used in Blazor WebAssembly and Blazor Server projects. (Note that streaming of big files is not supported in Blazor Server due to bandwidth problems.)

This is still a valid issue though, as that is a very valid use case. I just haven't prioritized this previously. Actually, this is more related to my Blazor.Streams project, so I might end up creating an issue there. What I have done previously, for my own customers, has been to get a stream from the file using the StreamAsync method and then reading small chunks of the file into an intermediate buffer while it is streamed like I have done here in my ReadableStream implementation but limiting the buffer size and putting in some Task.Yields or Delays between reading each chunk so that the Blazor Server circuit isn't blocked by this work in too long consecutive periods. This likewise opens up the possibility to update the user with upload progress while it happens i.e "Uploading progress 23% ..."

A more straightforward way to get around this limitation is to increase the message size limit for the SignalR connection to however big files you want to send which could look like this when configuring Server Side SignalR Hub connection settings in a Blazor Server project:

builder.Services.AddServerSideBlazor().AddHubOptions(o =>
{
    o.MaximumReceiveMessageSize = 1024 * 1024; // This is 1 Megabyte
});

from blazor.filesystemaccess.

KristofferStrube avatar KristofferStrube commented on July 23, 2024

I'll keep this issue open for bit longer so that I that I can keep track of the use case and either add more documentation for this case or resolve it in the Blazor.Streams project.

from blazor.filesystemaccess.

georg-jung avatar georg-jung commented on July 23, 2024

I think I found a rather easy and quite flexible streaming solution. Not sure if it has any downsides I'm currently overlooking, but it seems to work well for me without changing the SignalR message size. I tested it with files of around ~25 MB, which worked on localhost with a minor delay (roughly >1s <5s on my machine). It uses the same mechanisms as Blazor's InputFile component:

internal static class BlazorFileSystemAccessExtensions
{
    public static async Task<IJSStreamReference> GetFileStream(this FileSystemFileHandle fileHandle, CancellationToken cancellationToken = default)
    {
        return await fileHandle.JSReference.InvokeAsync<IJSStreamReference>("getFile", cancellationToken);
    }

    public static async Task<byte[]> ReadAllBytes(this IJSStreamReference jsStream, long maxAllowedSize = 512000, CancellationToken cancellationToken = default)
    {
        await using var s = await jsStream.OpenReadStreamAsync(maxAllowedSize, cancellationToken);
        var buffer = new byte[s.Length];
        using var ms = new MemoryStream(buffer);
        await s.CopyToAsync(ms, cancellationToken);
        return buffer;
    }

    public static async Task<byte[]> ReadAllBytes(this FileSystemFileHandle fileHandle, long maxAllowedSize = 512000, CancellationToken cancellationToken = default)
    {
        await using var fs = await fileHandle.GetFileStream(cancellationToken);
        return await fs.ReadAllBytes(maxAllowedSize, cancellationToken);
    }
}

Note that Microsoft recommends to avoid the ReadAllBytes pattern:

Avoid reading the incoming file stream directly into memory all at once. For example, don't copy all of the file's bytes into a MemoryStream or read the entire stream into a byte array all at once. These approaches can result in performance and security problems, especially for server-side components.

It could lead to DoS attacks / high memory pressure if the maxAllowedSize is chosen too large. My approach shares this downsides though with the corresponding implementations in Blazor.FileSystemAccess. Only using GetFileStream is not against the advice.

This works because the File object returned by FileSystemHandle.getFile() is a Blob and Blazor JS Interop can return IJSStreamReference for these.

from blazor.filesystemaccess.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.