I have a file uploader with a drop zone implemented in Blazor WebAssembly that uses the InputFile component and is based on the tutorial found here
It works great when a user selects (or drops) a file or multiple files. However I also want to enable the ability to drag in a directory (or multiple directories) of files along with any individually selected files.
I tried to add the "webkitdirectory" attribute as discussed here
This did allow for a directory of files to be uploaded, however it does not allow for individually selected files to be included nor does it allow for multiple folders (it seems to ignore all but the first directory selected).
Here is a simplified version showing both input controls on one page with an area that outputs the file names and mimetypes of the files available from the upload:
@page "/"
<style>
.dropArea {
border: 1px dashed #828282;
border-radius: 3px;
padding: 0px;
height: 160px;
width: 600px;
align-items: center;
justify-content: center;
cursor: pointer !important;
background-color: lightblue;
margin-bottom:40px;
}
.dropArea:hover {
background-color: blue;
}
.dropArea input[type=file] {
opacity: 0;
width: 100%;
height: 100%;
height: 230px !important;
width: 580px !important;
}
.dropAreaDrug {
background-color: blue;
}
.dropAreaDisabled {
background-color: white;
}
.dropAreaDisabled:hover {
cursor: default !important;
background-color: white;
}
.dropAreaDisabled input[type=file] {
opacity: 0;
width: 1px !important;
height: 1px !important;
}
</style>
<h3>Accepts images, but not folders:</h3>
<div class="dropArea @dropClass">
<InputFile title="" style="width:100%; height:100%; cursor:pointer"
OnChange="OnInputFileChange"
@ondragenter="HandleDragEnter"
@ondragleave="HandleDragLeave"
accept="image/jpeg"
multiple />
</div>
<h3>Accepts folders, but not images:</h3>
<div class="dropArea @dropClass">
<InputFile title="" style="width:100%; height:100%; cursor:pointer"
OnChange="OnInputFileChange"
@ondragenter="HandleDragEnter"
@ondragleave="HandleDragLeave"
accept="image/jpeg"
webkitdirectory
multiple />
</div>
<h3>Files Selected:</h3>
@if (Files != null)
{
@foreach (var file in Files)
{
<div>
> @file.Name (MimeType:@file.ContentType)
</div>
}
}
@code{
IReadOnlyList<IBrowserFile> Files;
string dropClass = string.Empty;
private void HandleDragEnter()
{
dropClass = "dropAreaDrug";
}
private void HandleDragLeave()
{
dropClass = string.Empty;
}
async Task OnInputFileChange(InputFileChangeEventArgs e)
{
dropClass = string.Empty;
try
{
if (e.FileCount > 0)
{
Files = e.GetMultipleFiles(500);
await StartUpload();
}
else
{
Files = null;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
throw;
}
}
public async Task StartUpload()
{
long maxAllowedSize = 30000000;
dropClass = "dropAreaDisabled";
foreach (var file in Files)
{
//Convert to Base64String and uplaod to my webservice:
var base64String = String.Empty;
using (var stream = file.OpenReadStream(maxAllowedSize))
{
byte[] buffer = new byte[stream.Length];
await stream.ReadAsync(buffer, 0, buffer.Length);
base64String = Convert.ToBase64String(buffer);
//POST to WebService here...
}
dropClass = string.Empty;
StateHasChanged();
}
}
}
If you drop selected files into the first control you get a list of all the files along with their mimetypes which I can then loop through and process. However in the second one individual files are ignored and only a single directory of files is listed.
Is there a way to have the control accept BOTH individual files as well as all the files in a directory (or multiple directories) so I can process a mix of both? I've seen this capability with things like OneDrive and Google Drive web applications so I know it is possible.
Ideally there is a solution that does not require custom JavaScript via JSInterop.