Skip to content

Commit d6090d1

Browse files
github-actions[bot]dimodiyordan-mitev
authored
Merge fileselect-validation-3266 into production (#3268)
* docs(FileSelect): Improve Validation documentation and examples * Update components/fileselect/validation.md Co-authored-by: Yordan <[email protected]> * Update _contentTemplates/upload/notes.md --------- Co-authored-by: Dimo Dimov <[email protected]> Co-authored-by: Yordan <[email protected]>
1 parent 778ac1d commit d6090d1

File tree

3 files changed

+84
-46
lines changed

3 files changed

+84
-46
lines changed

_contentTemplates/upload/notes.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#server-security-note
22

3-
>warning File upload and remove controllers can create application vulnerabilities. Learn about all possible security risks and how to avoid them. Do not trust any part of the upload or remove request and implement server-side validation.
3+
>warning File handling, saving and deletion can create application vulnerabilities. This includes any related controller methods. Learn about all possible security risks and how to avoid them. Do not trust the user files or requests, and implement server-side validation.
44
>
5-
* [ASP.NET Core Secuirty Considerations](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-6.0#security-considerations)
5+
* [ASP.NET Core Secuirty Considerations](https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads)
66
* [File Upload Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html)
77
* [Upload Path Traversal](https://security.stackexchange.com/questions/177307/path-traversal-via-filename)
88
>
9-
The controller methods in this documentation do not implement security measures for simplicity and brevity.
9+
The code examples in this documentation do not implement security measures for simplicity and brevity.
1010

1111
#end
1212

components/fileselect/events.md

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,25 @@ Property | Type | Description
3939
4040
## OnSelect
4141

42-
The `OnSelect` fires when one or more files have been selected. The selection of files is achieved either through the **Select Files** button or by dropping the files anywhere in the component.
42+
The `OnSelect` event fires each time when the user selects file(s) through the **Select Files** button or by drag and drop anywhere in the component.
4343

44-
The event handler receives a [`FileSelectEventArgs` object](#fileselectfileinfo). If you set its `IsCancelled` property to `true`, the component will ignore the user action and the selected files will not appear in the component file list.
44+
The event handler receives a [`FileSelectEventArgs` object](#fileselectfileinfo). If you set its `IsCancelled` property to `true`, the component ignores the user action and all newly selected files do not appear in the component file list.
45+
46+
`OnSelect` fires for both valid and invalid files. You can verify if the file is valid by checking the validation-related properties of each [`FileSelectFileInfo`](slug:fileselect-events#fileselectfileinfo) object. If necessary, the application can still handle invalid files, for example, read their content.
4547

4648
See the [example below](#example).
4749

4850
## OnRemove
4951

50-
The `OnRemove` fires when a file has been removed from the list of selected files either by clicking the **x** icon or by pressing the `Del` key.
52+
The `OnRemove` event fires when the user deletes a file from the list by clicking the **x** icon or by pressing the `Del` key.
53+
54+
The event handler receives a [`FileSelectEventArgs` object](#fileselectfileinfo). The `Files` collection in the event argument always contains a single `FileSelectFileInfo` object. This is unlike the `OnSelect` event where `Files` can include one or more files.
5155

52-
The event handler receives a [`FileSelectEventArgs` object](#fileselectfileinfo). The `Files` collection in the event argument always contains a single `FileSelectFileInfo` object. This is unlike the `OnSelect` event where `Files` may include one or more files.
56+
`OnRemove` fires for both valid and invalid files.
5357

5458
## Example
5559

56-
>caption Handling the `OnSelect` and `OnRemove` events of the FileSelect
60+
>caption Handle the FileSelect `OnSelect` and `OnRemove` events
5761
5862
````RAZOR
5963
@using System.Threading
@@ -66,35 +70,44 @@ The event handler receives a [`FileSelectEventArgs` object](#fileselectfileinfo)
6670
@using IONS = System.IO
6771
6872
69-
<div class="k-form-hint">
70-
Expected files: <strong>@string.Join(", ", AllowedExtensions)</strong>
71-
</div>
72-
7373
<TelerikFileSelect AllowedExtensions="@AllowedExtensions"
74-
OnRemove="@RemoveFiles"
75-
OnSelect="@HandleFiles">
74+
OnRemove="@OnFileRemove"
75+
OnSelect="@OnFileSelect">
7676
</TelerikFileSelect>
7777
78+
<div class="k-form-hint">
79+
Expected files: &nbsp; <strong>@string.Join(", ", AllowedExtensions)</strong>
80+
</div>
81+
7882
@code {
79-
private readonly List<string> AllowedExtensions = new() { ".jpg", ".png", ".gif" };
83+
private readonly List<string> AllowedExtensions = new() { ".gif", ".jpg", ".jpeg", ".png", ".svg" };
8084
8185
private Dictionary<string, CancellationTokenSource> Tokens { get; set; } = new();
8286
83-
private async Task HandleFiles(FileSelectEventArgs args)
87+
private async Task OnFileSelect(FileSelectEventArgs args)
8488
{
8589
foreach (var file in args.Files)
8690
{
87-
if (!file.InvalidExtension)
91+
if (file.InvalidExtension || file.InvalidMaxFileSize || file.InvalidMinFileSize)
8892
{
89-
// Read file in-memory.
90-
await ReadFile(file);
93+
// Skip invalid files.
94+
continue;
9195
9296
// OR
9397
94-
// Save to local file system.
95-
// This works only in server apps and the Upload component may be a better choice.
96-
//await UploadFile(file);
98+
// Cancel all files, but refactor the handler to iterate and validate all files before reading any of them.
99+
//args.IsCancelled = true;
100+
//return;
97101
}
102+
103+
// Read file in-memory.
104+
await ReadFile(file);
105+
106+
// OR
107+
108+
// Save to local file system.
109+
// This works only in server apps and the Upload component may be a better choice.
110+
//await UploadFile(file);
98111
}
99112
}
100113
@@ -117,7 +130,7 @@ The event handler receives a [`FileSelectEventArgs` object](#fileselectfileinfo)
117130
//await file.Stream.CopyToAsync(fs, Tokens[file.Id].Token);
118131
}
119132
120-
private async Task RemoveFiles(FileSelectEventArgs args)
133+
private async Task OnFileRemove(FileSelectEventArgs args)
121134
{
122135
foreach (var file in args.Files)
123136
{

components/fileselect/validation.md

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,43 +8,68 @@ published: true
88
position: 10
99
---
1010

11-
# FileSelect - Selected Files Validation
11+
# FileSelect File Validation
1212

1313
If you want to validate the selected files, you should implement the validation in two parts:
1414

15-
* client validation - performed by the Telerik FileSelect component
16-
* server validation - must be implemented in the application endpoints
15+
* Client validation&mdash;performed by the Telerik FileSelect component
16+
* Server validation&mdash;must be implemented in the application backend or endpoints
1717

18-
The Telerik FileSelect component offers parameters to validate the file selection on the client:
18+
## Parameters
1919

20-
* `Accept` - `string` - not validation per se, but this parameter can [instruct the browser what file types to allow users to select](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept).
21-
* `AllowedExtensions` - `List<string>` - a list of valid file extensions. Choosing other file types will mark them as invalid in the UI. The default value is `null`, which allows all extensions.
22-
* `MinFileSize`- `int?` - the minimum size of a file in bytes. Files with a smaller size will be marked as invalid in the UI.
23-
* `MaxFileSize`- `int?` - the maximum size of a file in bytes. Files with a larger size will be marked as invalid in the UI.
20+
The Telerik [FileSelect component offers parameters](slug:Telerik.Blazor.Components.TelerikFileSelect) to validate the file selection on the client:
2421

25-
>caption Client validation in the Telerik FileSelect component
22+
* `AllowedExtensions`
23+
* `MinFileSize`
24+
* `MaxFileSize`
2625

27-
For brevity, this sample does not showcase actual upload of the files. You can find an example in the [FileSelect Events article](slug:fileselect-events).
26+
Selected files that don't meet the defined criteria are marked as invalid in the component UI.
27+
28+
The FileSelect also provides an `Accept` parameter. It does not enforce validation, but [instructs the browser what file types to allow users to select](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept). This can also help users find the correct files more easily.
29+
30+
## Events
31+
32+
The [FileSelect fires its `OnSelect` and `OnRemove` events](slug:fileselect-events) for both valid and invalid files. The application can confirm file validity through the [event argument properties](slug:fileselect-events#fileselectfileinfo) and decide how to proceed.
33+
34+
## Example
35+
36+
For brevity, the code below does not handle the selected file. See a full example in the [FileSelect Events article](slug:fileselect-events#example).
37+
38+
>caption Telerik FileSelect file validation
2839
2940
````RAZOR
30-
@* Some images are only allowed, min size 1KB, max size 4MB *@
31-
32-
<div style="width:300px">
33-
<TelerikFileSelect AllowedExtensions="@AllowedExtensions"
34-
MinFileSize="@MinSize"
35-
MaxFileSize="@MaxSize">
36-
</TelerikFileSelect>
37-
<div class="k-form-hint">
38-
Expected files: <strong> JPG, PNG, JPEG </strong> between <strong>1KB</strong> and <strong>4MB</strong>.
39-
</div>
41+
<TelerikFileSelect AllowedExtensions="@AllowedExtensions"
42+
MinFileSize="@MinSize"
43+
MaxFileSize="@MaxSize"
44+
Multiple="false"
45+
OnSelect="@OnFileSelect">
46+
</TelerikFileSelect>
47+
48+
<div class="k-form-hint">
49+
Expected files: JPG, PNG, SVG between 1 KB and 4 MB.
4050
</div>
4151
4252
@code {
43-
public List<string> AllowedExtensions { get; set; } = new List<string>() { ".jpg", ".png", ".jpeg" };
53+
private readonly List<string> AllowedExtensions = new List<string>() { ".jpg", ".jpeg", ".png", ".svg" };
54+
55+
private const int MinSize = 1024;
56+
57+
private const int MaxSize = 4 * 1024 * 1024;
58+
59+
private void OnFileSelect(FileSelectEventArgs args)
60+
{
61+
FileSelectFileInfo file = args.Files.First();
4462
45-
public int MinSize { get; set; } = 1024;
63+
if (file.InvalidExtension || file.InvalidMaxFileSize || file.InvalidMinFileSize)
64+
{
65+
// Optionally, ignore the user action completely.
66+
// The selected file(s) will not appear in the file list.
67+
//args.IsCancelled = true;
68+
return;
69+
}
4670
47-
public int MaxSize { get; set; } = 4 * 1024 * 1024;
71+
// Handle selected valid file...
72+
}
4873
}
4974
````
5075

0 commit comments

Comments
 (0)