Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maximum allowed size of OpenReadStream

Tags:

blazor

What is the maximum allowed size of OpenReadStream? Right now, using 10MB. But I believe there has to be a certain cap. Can it take GB?

like image 909
Sarahrb Avatar asked Sep 12 '25 05:09

Sarahrb


1 Answers

In ASP.NET Core 5.0, there was a 2 GB framework file size limit for uploading files. However, starting with ASP.NET Core 6.0 and later versions, the framework doesn't impose a maximum file size limit.

By default, files no larger than 512,000 bytes (500 KB) in size are allowed to be read before any further reads would result in an exception. This limit is present to prevent developers from accidentally reading large files into memory.

// Uses the default max allowed size of 500 KB (512,000 bytes)
await myFile.OpenReadStream().ReadAsync(buffers);

To set a custom file upload size, you can override the maxAllowedSize parameter in the OpenReadStream method, as shown below:

Example for 300 KB limit:
// Accept a file up to 307200 bytes (300 KB) in size
await myFile.OpenReadStream(maxAllowedSize: 1024 * 300).ReadAsync(buffers);
Example for 2 GB limit:
// Define the maximum file size allowed (2 GB)
long maxFileSize = 2L * 1024L * 1024L * 1024L;

// Accept a file up to the specified size
await myFile.OpenReadStream(maxAllowedSize: maxFileSize).ReadAsync(buffers);

For smaller file sizes less than 2GB, using int is sufficient. However, for larger file sizes, use long to avoid integer overflow. The L suffix in 2L and 1024L explicitly declares these values as 64-bit long integers, ensuring accurate calculations for large file sizes.

The OpenReadStream method can indeed handle files in the gigabyte range. The maximum allowed size is limited only by the available system resources and any application-specific constraints you set.


UPDATE: I tested the file upload with a file that is 2 GB in size, and it was uploaded successfully.

DEMO:

Image showing upload of 2GB file using Blazor Server

CODE:
This Blazor Server code example demonstrates uploading large files:

@page "/"
@using System.IO
@using System.Buffers
@inject IWebHostEnvironment Env

<h1 class="mb-4">Blazor Server File Upload</h1>

<!-- Alert message display -->
<div class="@AlertClass" role="alert">
    @AlertMessage
</div>

<!-- Progress bar for file upload -->
<div class="progress mb-3" style="height: 20px;">
    <div class="progress-bar" role="progressbar" style="width: @ProgressPercentage%;" aria-valuenow="@ProgressPercentage" aria-valuemin="0" aria-valuemax="100">@ProgressPercentage% Complete</div>
</div>

<!-- File upload form -->
<form @onsubmit="OnSubmitAsync" class="needs-validation" novalidate>
    <div class="input-group mb-3">
        <InputFile @key="InputFileId" class="form-control" id="inputFile" OnChange="OnInputFileChange" aria-describedby="uploadButton" required />
        <button class="btn btn-primary" type="submit" id="uploadButton" disabled="@IsUploadDisabled">
            <span class="oi oi-cloud-upload" aria-hidden="true"></span> Upload Selected File
        </button>
    </div>
    <div class="invalid-feedback">
        Please select a file to upload.
    </div>
</form>

@code {
    // Constants for file size and allowed extensions
    private const long MaxFileSize = 2L * 1024L * 1024L * 1024L; // 2 GB
    private static readonly string[] AllowedExtensions = { ".zip", ".rar", ".bin" };

    // Properties for UI state management
    private MarkupString AlertMessage { get; set; } = new("<strong>No file selected</strong>");
    private string AlertClass { get; set; } = "alert alert-info";
    private int ProgressPercentage { get; set; }
    private IBrowserFile? SelectedFile { get; set; }
    private bool IsUploadDisabled { get; set; } = true;
    private Guid InputFileId { get; set; } = Guid.NewGuid();

    // Handle file selection
    private void OnInputFileChange(InputFileChangeEventArgs e)
    {
        SelectedFile = e.GetMultipleFiles().FirstOrDefault();
        ProgressPercentage = 0;
        IsUploadDisabled = true;

        // Validate selected file
        if (SelectedFile is null)
        {
            SetAlert("alert alert-warning", "oi oi-warning", "No file selected.");
            return;
        }

        if (SelectedFile.Size > MaxFileSize)
        {
            SetAlert("alert alert-danger", "oi oi-ban", $"File size exceeds the limit. Maximum allowed size is <strong>{MaxFileSize / (1024 * 1024)} MB</strong>.");
            return;
        }

        string fileExtension = Path.GetExtension(SelectedFile.Name).ToLowerInvariant();
        if (!AllowedExtensions.Contains(fileExtension))
        {
            SetAlert("alert alert-danger", "oi oi-warning", $"Invalid file type. Allowed file types are <strong>{string.Join(", ", AllowedExtensions)}</strong>.");
            return;
        }

        SetAlert("alert alert-info", "oi oi-info", $"<strong>{SelectedFile.Name}</strong> ({SelectedFile.Size} bytes) file selected.");
        IsUploadDisabled = false;
    }

    // Handle file upload
    private async Task OnSubmitAsync()
    {
        if (SelectedFile is null) return;

        IsUploadDisabled = true;
        await using Stream stream = SelectedFile.OpenReadStream(MaxFileSize);
        string path = Path.Combine(Env.WebRootPath, SelectedFile.Name);
        await using FileStream fs = File.Create(path);

        // Set up buffer for file reading
        const int bufferSize = 512 * 1024; // 512 KB
        byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
        long totalBytesRead = 0;
        long fileSize = SelectedFile.Size;

        // Set up timer for UI updates
        using var timer = new Timer(_ => InvokeAsync(StateHasChanged));
        timer.Change(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500));

        try
        {
            // Read and write file in chunks
            int bytesRead;
            while ((bytesRead = await stream.ReadAsync(buffer)) != 0)
            {
                totalBytesRead += bytesRead;
                ProgressPercentage = (int)(100 * totalBytesRead / fileSize);
                await fs.WriteAsync(buffer.AsMemory(0, bytesRead));
            }
        }
        finally
        {
            ArrayPool<byte>.Shared.Return(buffer);
        }

        // Clean up and update UI
        timer.Change(Timeout.Infinite, Timeout.Infinite);
        ProgressPercentage = 100;
        SetAlert("alert alert-success", "oi oi-check", $"<strong>{SelectedFile.Name}</strong> ({SelectedFile.Size} bytes) file uploaded on server.");
        InputFileId = Guid.NewGuid();
        StateHasChanged();
    }

    // Helper method to set alert message and style
    private void SetAlert(string alertClass, string iconClass, string message)
    {
        AlertClass = alertClass;
        AlertMessage = new MarkupString($"<span class='{iconClass}' aria-hidden='true'></span> {message}");
    }
}

Important information about this code example:

  • The code was tested in .NET 8 Blazor Web App with Interactive render mode set to "Server" and Interactivity location set to "Global".
  • The long data type is used to represent the file size accurately. This is essential when working with files larger than 2 GB, which can't be represented by an int.
  • IWebHostEnvironment is used to access the server environment for file operations.
  • Note that this example demonstrates uploading large file sizes as explained above. For Blazor WebAssembly, you would need to adjust the code to send the file through an API to save it locally on the server.
like image 183
Ibrahim Timimi Avatar answered Sep 14 '25 18:09

Ibrahim Timimi