+
+@code {
+ FileUpload _basicFileControl, _imageFileControl, _multiFileControl;
+ string _basicStatusText, _imageStatusText, _multiStatusText;
+
+ void CheckBasicFile() => _basicStatusText = "Basic file control clicked";
+ void CheckImageFile() => _imageStatusText = "Image control clicked";
+ void CheckMultiFiles() => _multiStatusText = "Multi-file control clicked";
+}
From 3357d71ecad8cada3d106038cf1aba0ed88aed1f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 17:45:15 +0000
Subject: [PATCH 4/4] Address code review feedback - improve security and async
patterns
Co-authored-by: csharpfritz <78577+csharpfritz@users.noreply.github.com>
---
src/BlazorWebFormsComponents/FileUpload.razor | 4 +--
.../FileUpload.razor.cs | 26 ++++++++++++++++---
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/src/BlazorWebFormsComponents/FileUpload.razor b/src/BlazorWebFormsComponents/FileUpload.razor
index 3827c5a4..8c1b97ea 100644
--- a/src/BlazorWebFormsComponents/FileUpload.razor
+++ b/src/BlazorWebFormsComponents/FileUpload.razor
@@ -4,11 +4,11 @@
{
}
diff --git a/src/BlazorWebFormsComponents/FileUpload.razor.cs b/src/BlazorWebFormsComponents/FileUpload.razor.cs
index 6c4abf2a..d0d832b6 100644
--- a/src/BlazorWebFormsComponents/FileUpload.razor.cs
+++ b/src/BlazorWebFormsComponents/FileUpload.razor.cs
@@ -38,6 +38,22 @@ public partial class FileUpload : BaseStyledComponent
/// Gets the contents of the uploaded file as a byte array.
/// For multiple files, returns the first file's content.
///
+ public async Task GetFileBytesAsync()
+ {
+ if (!HasFile) return Array.Empty();
+
+ var file = _currentFile ?? _currentFiles.FirstOrDefault();
+ using var stream = file.OpenReadStream(MaxFileSize);
+ using var memoryStream = new MemoryStream();
+ await stream.CopyToAsync(memoryStream);
+ return memoryStream.ToArray();
+ }
+
+ ///
+ /// Gets the contents of the uploaded file as a byte array (synchronous).
+ /// For multiple files, returns the first file's content.
+ /// Note: Prefer GetFileBytesAsync() for better async/await patterns.
+ ///
public byte[] FileBytes
{
get
@@ -98,11 +114,11 @@ public PostedFileWrapper PostedFile
public string Accept { get; set; }
///
- /// Gets or sets the maximum file size in bytes. Default is 512000 (500KB) to match Blazor defaults.
+ /// Gets or sets the maximum file size in bytes. Default is 512000 bytes (~500 KiB).
/// Can be increased for larger files, but be mindful of memory usage.
///
[Parameter]
- public long MaxFileSize { get; set; } = 512000; // 500KB default
+ public long MaxFileSize { get; set; } = 512000; // ~500 KiB default
///
/// Gets or sets the tooltip text displayed when hovering over the control.
@@ -145,6 +161,7 @@ public IEnumerable GetMultipleFiles()
///
/// Saves all uploaded files to the specified directory.
+ /// File names are sanitized to prevent directory traversal attacks.
///
/// The directory path where files should be saved.
/// A list of saved file paths.
@@ -160,7 +177,9 @@ public async Task> SaveAllFiles(string directory)
foreach (var file in files)
{
- var path = Path.Combine(directory, file.Name);
+ // Sanitize filename to prevent directory traversal attacks
+ var safeFileName = Path.GetFileName(file.Name);
+ var path = Path.Combine(directory, safeFileName);
using var stream = file.OpenReadStream(MaxFileSize);
using var fileStream = new FileStream(path, FileMode.Create);
await stream.CopyToAsync(fileStream);
@@ -210,6 +229,7 @@ internal PostedFileWrapper(IBrowserFile file, long maxFileSize)
///
/// Gets a Stream object that points to the uploaded file.
+ /// Note: The caller is responsible for disposing the returned stream.
///
public Stream InputStream => _file.OpenReadStream(_maxFileSize);