The problem arises from the confusion in handling files based on their sizes.
For this particular context, I'll constrain the subject solely to a Blazor web app and a SQL Server database.
Moreover, for a more detailed overview, according to the research findings from To BLOB or Not To BLOB: Large Object Storage in a Database or a Filesystem:
Application designers often face the question of whether to store large objects in a filesystem or in a database. Often this decision is made for application design simplicity. Sometimes, performance measurements are also used. This paper looks at the question of fragmentation – one of the operational issues that can affect the performance and/or manageability of the system as deployed long term. As expected from the common wisdom, objects smaller than 256K are best stored in a database while objects larger than 1M are best stored in the filesystem. Between 256K and 1M, the read:write ratio and rate of object overwrite or replacement are important factors. We used the notion of “storage age” or number of object overwrites as way of normalizing wall clock time. Storage age allows our results or similar such results to be applied across a number of read:write ratios and object replacement rates.
Which, in turn, I decided to implement FILESTREAM in handling large files.
But I was thinking, can these figures, smaller than 256K and larger than 1M, be applied to the app-side's file-size comparison logic? Meaning, files smaller than 256K are considered small file sizes, while files larger than 1M are considered large file sizes. I think 1M is equivalent to 1MB. This matter has relationship with this article: ASP.NET Core Blazor file uploads.
This is crucial for me to ensure that the decision-making in file handling is handled properly within the database and application phase of my system architecture.
For a more detailed concept, I was trying to implement a maxAllowedSize to an OpenReadStream to enforce and filter the limit of file size to be collected and stored, say, for example, to prevent large files from being uploaded:
<InputFile class="btn btn-outline-primary" OnChange="HandleImageUpload" accept="image/*" />@if (myModel.Img is not null){<img src="@myModel.Img" class="img-thumbnail my-3" alt="Test Image" />}@code { private async Task HandleImageUpload(InputFileChangeEventArgs e) { long threeMB = 3L * 1024L * 1024L; //3 MB limit var file = e.File; var stream = file.OpenReadStream(maxAllowedSize: threeMB); var buffer = new byte[file.Size]; await stream.ReadAsync(buffer); var base64 = Convert.ToBase64String(buffer); myModel.Img = $"data:{file.ContentType};base64,{base64}"; }}Therefore, I would consider the above method as specifying maxAllowedSize with threeMB as a large file.
My question is,
- am I on the right track?
Note that I am facing an issue in the HandleImageUpload method, where I can't filter the file size. This neither throws an exception nor rejects the file selection, which is larger than 3MB.
And my question about this case is,
- It seems I am missing something in the code which still allowed file sizes more than
3MB.
I like the direct specifying of the restriction of the file max size limit, but it behaves unexpectedly. I didn't get the point of setting this up: var stream = file.OpenReadStream(maxAllowedSize: threeMB); if this doesn't behave as expected, so I needed to refactor the code into this:
private async Task HandleImageUpload(InputFileChangeEventArgs e){ long threeMB = 3L * 1024L * 1024L; //3 MB limit var file = e.File; if (file.Size > threeMB) { await JS.InvokeVoidAsync("showLiveToastError"); } else { var stream = file.OpenReadStream(maxAllowedSize: threeMB); var buffer = new byte[file.Size]; await stream.ReadAsync(buffer); var base64 = Convert.ToBase64String(buffer); myModel.Img = $"data:{file.ContentType};base64,{base64}"; }}Hence, what's the point of this setting: var stream = file.OpenReadStream(maxAllowedSize: threeMB);?
I was expecting this:
Reading one file or multiple files larger than 500 KB (3 MB) results in an exception.
I'm consciously aware that this thread has two different subjects, but I decided to combine them to close the gap between my confusion and what I'm really trying to achieve.
