FileUpload
in namespace DotVVM.BusinessPack.Controls
Renders a FileUpload control supporting HTML 5 upload features (drag & drop, directory upload, image previews, etc.).
Usage & Scenarios
Allows the user to upload one or multiple files asynchronously.
Upload Configuration
The upload works on the background and starts immediately when the user selects the files. To make file uploading work, you have to specify where the temporary files will be uploaded.
The recommended strategy is to store the uploaded files in your application directory or in the temp directory (if your app have the appropriate permissions).
To define this, you have to register the UploadedFileStorage
in the IDotvvmServiceConfigurator
.
public void ConfigureServices(IDotvvmServiceCollection options)
{
options.AddUploadedFileStorage("App_Data/Temp");
}
Using the Control
Then, you need to bind the FileUpload
control to an UploadData
object. It holds references to the files
the user has selected and uploaded.
The UploadData
object also has a useful property IsBusy
which indicates whether the file upload is still in progress. You can use it e.g. on the button's Enabled
property to disallow the user to continue until the upload is finished.
Retrieving the Stored Files
The UploadData
object contains only unique IDs of uploaded files. To get the file contents, you have to retrieve it using the IUploadedFileStorage
service.
public class UploadViewModel
{
private readonly IUploadedFileStorage storage;
public UploadViewModel(IUploadedFileStorage storage)
{
this.storage = storage;
}
public async Task ProcessFiles()
{
foreach (var file in UploadData.Files)
{
if (file.IsAllowed)
{
// get the stream of the uploaded file and do whatever you need to do
var stream = storage.GetFile(file.FileId);
// OR you can just move the file from the temporary storage somewhere else
var targetPath = Path.Combine(uploadPath, file.FileId + ".bin");
await storage.SaveAsAsync(file.FileId, targetPath);
// it is a good idea to delete the file from the temporary storage
// it is not required, the file would be deleted automatically after the timeout set in the DotvvmStartup.cs
await storage.DeleteFileAsync(file.FileId);
}
}
}
}
The FileUpload control checks whether the file extension or MIME type matches the AllowedFileTypes
definition, and that the file size does not exceed the MaxFileSize
.
You can use the IsFileTypeAllowed
and IsMaxSizeExceeded
properties of the file in the UploadData
object to find out why the file was not allowed.
However, please note that the validation is essentially only performed client-side and cannot be trusted for anything beyond displaying error messages.
Any user able to press F12 can modify all unencrypted view model properties, including those in UploadedFilesCollection
.
Make sure to validate the file characteristics based on the data from IUploadedFileStorage
when it is important.
Â
Sample 1: Basic Usage
The FileUpload
control has the Data
property (of type UploadData
). Each file will get a unique ID when it is uploaded. This ID will be then stored in the Files
collection.
The AllowMultipleFiles
property specifies whether the user can select multiple files in the file browser window. It also enables directory upload in modern browsers.
<bp:FileUpload Data="{value: Upload}"
AllowMultipleFiles="true" />
using System.Collections.Generic;
using DotVVM.BusinessPack.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.FileUpload.sample1
{
public class ViewModel : DotvvmViewModelBase
{
public UploadData Upload { get; set; } = new UploadData();
}
}
Sample 2: UploadCompleted Event
The UploadCompleted
event is fired automatically when all files are uploaded.
<bp:FileUpload Data="{value: Upload}"
UploadCompleted="{command: ProcessFile()}" />
{{value: Message}}
using System.Collections.Generic;
using DotVVM.BusinessPack.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.FileUpload.sample2
{
public class ViewModel : DotvvmViewModelBase
{
public string Message { get; set; }
public UploadData Upload { get; set; } = new UploadData();
public void ProcessFile()
{
// do what you have to do with the uploaded files
Message = "ProcessFile() was called.";
}
}
}
Sample 3: Processing the Files
You can use the Upload.IsBusy
property to determine whether the upload is still in progress or not.
<bp:FileUpload Data="{value: Upload}" />
<p>
<bp:Button Text="Save Files"
Click="{command: Process()}"
Enabled="{value: !Upload.IsBusy}" />
</p>
using System.IO;
using System.Threading.Tasks;
using DotVVM.BusinessPack.Controls;
using DotVVM.Core.Storage;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.FileUpload.sample3
{
public class ViewModel : DotvvmViewModelBase
{
private readonly IUploadedFileStorage fileStorage;
public ViewModel(IUploadedFileStorage fileStorage)
{
this.fileStorage = fileStorage;
}
public UploadData Upload { get; set; } = new UploadData();
public async Task Process()
{
var folderPath = GetFolderPath();
// save all files to disk
foreach (var file in Upload.Files)
{
var filePath = Path.Combine(folderPath, file.FileId + ".bin");
await fileStorage.SaveAsAsync(file.FileId, filePath);
await fileStorage.DeleteFileAsync(file.FileId);
}
// clear the data so the user can continue with other files
Upload.Clear();
}
private string GetFolderPath()
{
var folderPath = Path.Combine(Context.Configuration.ApplicationPhysicalPath, "MyFiles");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
return folderPath;
}
}
}
Sample 4: Drag & Drop Upload
The drag & drop upload is supported out-of-the-box. And if you need to customize its look and feel, you can use the DropTemplate
property. It allows you to specify contents visible when user drags files over the FileUpload
control.
The DropTemplate
is by default rendered over all contents of the control. If you want to open an upload dialog after an element is clicked on, mark it with bp-select-files
CSS class.
<bp:FileUpload Data="{value: Upload}">
<DropTemplate>
Drop files here!
</DropTemplate>
<!-- build a custom UI here -->
<dot:Repeater DataSource="{value: Upload.Files}">
<div>
{{value: FileName}}
</div>
</dot:Repeater>
<div>
<bp:Button Text="Upload" Type="Primary" Click="{command: UploadFiles()}"/>
</div>
</bp:FileUpload>
using System.Collections.Generic;
using DotVVM.BusinessPack.Controls;
using DotVVM.Framework.ViewModel;
namespace DotvvmWeb.Views.Docs.Controls.businesspack.FileUpload.sample4
{
public class ViewModel : DotvvmViewModelBase
{
public UploadData Upload { get; set; } = new UploadData();
public void UploadFiles()
{
// Custom Event
}
}
}
Properties
Name | Type | Description | Notes | Default Value | |
---|---|---|---|---|---|
AllowedFileTypes | String | Gets or sets the types of files that the server accepts. It must be a comma-separated list of unique content type specifiers (eg. ".jpg,image/png,audio/*"). |
attribute
static value
|
null | |
AllowMultipleFiles | Boolean | Gets or sets whether the user can select multiple files at once. It is enabled by default. |
attribute
static value
|
True | |
ClientIDMode | ClientIDMode | Gets or sets the client ID generation algorithm. |
attribute
static value
|
Static | |
ContentTemplate | ITemplate | Gets or sets a template rendering contents of the control. |
inner element
static value
bindable
default
|
null | |
Data | UploadData | Gets or sets the file upload data (e.g. list of uploaded files, upload progress). |
attribute
bindable
|
null | |
DataContext | Object | Gets or sets a data context for the control and its children. All value and command bindings are evaluated in context of this value. The DataContext is null in client-side templates. |
attribute
bindable
|
null | |
DeleteFileIcon | IconBase | Gets or sets the icon displayed on the button used to delete uploaded files. |
inner element
static value
bindable
|
null | |
DragFilesHereText | String | Gets or sets the text informing about drag&drop upload; usually displayed next to the upload button. The default value is "or drag them here.". |
attribute
static value
|
or drag them here. | |
DropTemplate | ITemplate | Gets or sets the template displayed when files are dragged over the control. |
inner element
static value
|
null | |
Enabled | Boolean | Gets or sets a value indicating whether the control is enabled and can be modified. |
attribute
static value
bindable
|
True | |
GenericErrorText | String | Gets or sets the text displayed when a generic / unknown error occurs. The default value is "Upload has failed.". |
attribute
static value
|
Upload has failed. | |
ID | String | Gets or sets the control client ID within its naming container. |
attribute
static value
bindable
|
null | |
IncludeInPage | Boolean | Gets or sets whether the control is included in the DOM of the page. |
attribute
bindable
|
True | |
MaxFileSize | Int32? | Gets or sets the maximum size of files in megabytes (MB). The size is not limited by default. |
attribute
static value
|
null | |
UploadButtonText | String | Gets or sets the text displayed on the upload button. The default value is "Select files". |
attribute
static value
|
Select files | |
Visible | Boolean |
attribute
bindable
|
True |
Events
Name | Type | Description | |
---|---|---|---|
UploadCompleted | Command | Gets or sets a command that is triggered when the upload is complete. |