DxFileInput Class
A component that allows you to access the contents of selected files directly in razor code.
Namespace: DevExpress.Blazor
Assembly: DevExpress.Blazor.v24.1.dll
NuGet Package: DevExpress.Blazor
Declaration
public class DxFileInput :
DxControlComponent<FileInputJSInteropProxy>,
IFileInputViewOwner,
IUploadViewOwner
Remarks
The DevExpress File Input component for Blazor allows users to select files in the Open dialog or drag these files onto a drop zone. The component supplies a Stream that allows you to read file content for each selected file. Once the read operation is completed, you can send the file to another destination, save it to the file system, or display the file’s content on a web page.
Note
The File Input component does not upload selected files automatically. Handle the FilesUploading event to upload files.
Upload vs. File Input
DevExpress Blazor UI Component Library includes two components that allow you to handle file upload. The key differences between these components are outlined below:
- DxUpload
- This component requires that you create a web API controller in your application project or separate web API project. Once a user selects a file, the Upload component packs the file into an Ajax request and sends this request to the controller that processes the file.
DxFileInput
- This component allows you to access and process contents of selected files directly in razor code. To configure the component, you should implement file upload in the FilesUploading event handler.
Add a File Input to a Project
Follow the steps below to add a File Input component to an application:
- Use a DevExpress Project Template to create a new Blazor Server or Blazor WebAssembly application. If you use a Microsoft project template or already have a Blazor project, configure your project to include DevExpress Blazor components.
- Add the following markup to a
.razor
file:<DxFileInput>
…</DxFileInput>
. - Implement file upload.
- Specify other File Input options (see the sections below).
Implement File Upload
The File Input component does not upload selected files automatically. Instead, the component raises the FilesUploading
event once you or users start (or restart) an upload operation.
Handle the FilesUploading event to access selected Files and call a file’s OpenReadStream method to read file content. Once the read operation is completed, you can send the file to another destination, save it to the file system, or display file content on a web page.
Note
Do not read a stream directly in memory to avoid performance and security-related issues. Instead, copy the stream to a file on a disk or pass file content to an external service.
The following example reads contents of uploaded files:
<DxFileInput FilesUploading="OnFilesUploading" />
@code {
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (var file in args.Files) {
try {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
catch (OperationCanceledException ex) {
// Handle the cancel action here
}
}
}
}
Based on the render mode, the File Input component streams file content in one of the following ways:
- In Interactive WebAssembly mode, the component streams file data directly to razor code in the user browser.
- In Interactive Server mode, the component streams file data from the client over the SignalR connection to the server’s razor code.
If you use the ReadAsync method to read stream content, note that this method may read fewer bytes than requested. To ensure correct read operations, call the ReadAsync method within the while
loop as follows:
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (var file in args.Files){
int fileSize = (int)file.Size;
Stream stream = file.OpenReadStream(fileSize);
try {
int totalBytesRead = 0;
int bytesReadCount = 0;
byte[] FileBytes = new byte[fileSize];
do {
bytesReadCount = await stream.ReadAsync(FileBytes, totalBytesRead, fileSize - totalBytesRead);
totalBytesRead += bytesReadCount;
} while (bytesReadCount != 0);
}
finally {
stream?.Close();
}
}
}
File List and Upload Operations
Once a user selects files in the Open dialog or drags files onto a drop zone, the File Input component adds these files to the file list. The file list displays each file’s upload status and upload, cancel, reload, and remove buttons. On the image below, the file list contains 4 files in different states:
Handle the SelectedFilesChanged event to access the collection of files in the file list. Call the following methods to manage these files in code:
Start Upload | Cancel Upload | Restart Canceled Upload | Remove Files from List | |
---|---|---|---|---|
One File | UploadFile | CancelFileUpload | ReloadFile | RemoveFile |
Multiple Files | UploadFiles | CancelFilesUpload | ReloadFiles | RemoveFiles |
All Files | UploadAllFiles | CancelAllFilesUpload | ReloadAllFiles | RemoveAllFiles |
Disable the AllowCancel property to hide cancel buttons and prevent users from canceling upload operations. Set the ShowFileList property to false
to hide the file list.
Upload Modes
In Instant
upload mode (default), upload buttons are hidden. Once a user selects files in the Open dialog or drags files onto a drop zone, the File Input component adds these files to the file list and starts an upload operation.
Set the UploadMode property to OnButtonClick
to display upload buttons and start upload operations in response to a button click:
<DxFileInput UploadMode="UploadMode.OnButtonClick" FilesUploading="OnFilesUploading" />
@code {
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (IFileInputSelectedFile file in args.Files) {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
}
}
Multiple File Upload
The File Input component allows users to add one file to the file list at a time. Enable the AllowMultiFileUpload property to allow users to add multiple files to the file list simultaneously. The MaxFileCount property specifies the maximum size of the file list. When the file list reaches its size limit, users can add new files only after they remove one or more uploaded files.
Note
We do not recommend that you increase the MaxFileCount property value beyond 1000
(default). However, you can set this property to 0
to remove the size limit of the file list.
The following example allows users to add multiple files to the file list:
<DxFileInput AllowMultiFileUpload="true" MaxFileCount="500" FilesUploading="OnFilesUploading" />
@code {
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (IFileInputSelectedFile file in args.Files) {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
}
}
Drag and Drop
You can enable drag and drop functionality in the File Input component. To enable this functionality, create a drop zone and assign its CSS selector to the ExternalDropZoneCssSelector property. The ExternalDropZoneDragOverCssClass property specifies the CSS class applied to this drop zone when users drag files over it.
The following example implements a drop zone container for the File Input component:
<div id="overviewDemoDropZone" class="card custom-drop-zone bg-light rounded-3 w-100 m-0">
<span class="drop-file-icon mb-3"></span>
<span>Drag and Drop File Here</span>
</div>
<DxFileInput FilesUploading="OnFilesUploading"
ExternalDropZoneCssSelector="#overviewDemoDropZone"
ExternalDropZoneDragOverCssClass="bg-light border-secondary text-dark" />
@code {
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (var file in args.Files) {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
}
}
Validate Files
Built-In Validation
Once a user adds a file to the file list, the File Input component validates the file’s size and extension. If validation fails, the File Input hides the upload button and displays an error message. Specify the following properties to place additional restriction on files that users can upload:
- AcceptedFileTypes
- Specifies MIME types users can add to the file list.
- AllowedFileExtensions
- Specifies file extensions that the File Input component can upload.
- MaxFileSize
- Specifies the maximum file size in bytes.
- MinFileSize
- Specifies the minimum file size in bytes.
The following example validates size and extensions of uploaded files:
<DxFileInput MinFileSize="1000"
MaxFileSize="4000000"
FilesUploading="OnFilesUploading"
AllowedFileExtensions="@(new List<string> { ".jpg", ".jpeg", ".gif", ".png" })" />
@code {
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (IFileInputSelectedFile file in args.Files) {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
}
}
Custom Validation
To introduce secure file upload operations to your application, we recommend that you add different validation types to the FilesUploading event’s handler, for example:
- Validate the file name. Pass the Name property value to the Path.GetFileName method to obtain the actual file name.
- Limit file name length and restrict allowed characters.
If you save the file to a real file system, check whether the result file path is within the expected root directory. Call the Path.GetFullPath method to resolve path information:
var rootDirectory = new Directorylnfo("."); var resolvedPath = Path.GetFullPath(Path.Combine(rootDirectory.FullName, Path.GetFileName(file.Name)) ) ; if (!resolvedPath.StartsWith(rootDirectory.FullName + Path.DirectorySeparatorChar)) { throw new Exception(); }
Limit file size.
Validate file extensions and manage allowed extensions. Call the Path.GetExtension method to obtain the actual file extension:
var extension = Path.GetExtension(file.Name).ToUpperInvariant(); if (!imageExtensions.Contains(extension)) throw new InvalidOperationException();
The following code sample validates sizes and extensions of uploaded files:
<DxFileInput AllowedFileExtensions="imageExtensions"
MaxFileSize="MaxValidFileSize"
FilesUploading="OnFilesUploading" />
@code {
const long MaxValidFileSize = 4_000_000;
List<string> imageExtensions = new List<string> {".JPG", ".JPEG", ".GIF", ".PNG"};
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (var file in args.Files) {
try {
var extension = Path.GetExtension(file.Name).ToUpperInvariant();
if (imageExtensions.Contains(extension) && file.Size <= MaxValidFileSize) {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
else
throw new Exception();
}
catch (Exception ex) {
// Handle exceptions here
}
}
}
}
For more information and examples, refer to the following topics:
Select Button Customization
The Select File button invokes the Open dialog. In this dialog, users can select files that the File Input component should upload. Specify the SelectButtonText property to change the caption of the built-in select button:
<DxFileInput FilesUploading="OnFilesUploading" SelectButtonText="Select My File" />
@code {
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (IFileInputSelectedFile file in args.Files) {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
}
}
Disable the ShowSelectButton property to hide the built-in select button. Specify the ExternalSelectButtonCssSelector property to implement an external select button.
The following example implements a drop zone that invokes the Open dialog on click:
<div id="overviewDemoDropZone" class="card custom-drop-zone bg-light rounded-3 w-100 m-0">
<span>Drag & Drop a file</span>
<span>…or click to browse for a file instead.</span>
</div>
<DxFileInput FilesUploading="OnFilesUploading"
ExternalSelectButtonCssSelector="#overviewDemoDropZone"
ExternalDropZoneCssSelector="#overviewDemoDropZone" />
@code {
async Task OnFilesUploading(FilesUploadingEventArgs args) {
foreach (var file in args.Files) {
/* The following code is intended for demonstration purposes only.
Do not read a stream directly in memory to avoid performance and security-related issues. */
using var stream = new System.IO.MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(stream);
}
}
}
Keyboard Navigation
The DevExpress Blazor File Input component supports keyboard shortcuts that allow users to navigate between the component’s buttons. Keyboard navigation is implemented on the client and works seamlessly in Blazor Server apps with a slow connection.
The following shortcut keys are available:
Shortcut Keys | Description |
---|---|
Tab | Moves focus to the next button. |
Shift + Tab | Moves focus to the previous button. |
Enter, Space | Presses the focused button. |
Troubleshooting
If a Blazor application throws unexpected exceptions, refer to the following help topic: Troubleshooting.