Hoje vamos usar o componente InputFile para enviar arquivos e permitir o recurso drag and drop para selecionar os arquivos a enviar. |
Se você esta chegando agora e não sabe o que é o Blazor leia o artigo ASP .NET Core - Iniciando com o Blazor - Macoratti; se você já conhece e quer saber mais pode fazer o curso de Blazor Essencial.
No artigo Blazor - Upload de arquivos , eu mostrei como enviar arquivos usando o componente InputFile.
Hoje vamos retomar o uso do componente para enviar arquivos mas vamos incluir a funcionalidade de poder arrastar e soltar arquivos para fazer o Upload.
Vamos criar o projeto no ambiente .NET 5.0 RC1 e usar o Visual Studio 2019 Community Preview na versão 16.8.0 Preview 6.
Recursos usados:
Criando o projeto no VS Community 2019
Abra o VS 2019 Community (versão mínima 16.6) e selecione a opção Create a New Project;
A seguir selecione a opção Blazor app e clique em next;
Informe o nome do projeto : Blazor_DragDropUpload a localização e clique em Create;
Selecione a opção - Blazor Server App e escolha .NET 5.0. Não vamos usar autenticação e vamos habilitar o https.
Clique no botão Create para criar o projeto.
Com o projeto criado vamos limpar o projeto excluindo os arquivos abaixo e suas referências:
Também remova do arquivo NavMenu.razor as opções de Menu para Counter e FetchData deixando apenas o link do menu para Home.
Alterando o código do arquivo Index.razor
Vamos definir o código para realizar o Upload e permitir o drag and drop no arquivo Index.razor da pasta Pages.
No arquivo _Imports.razor vamos incluir 2 namespaces: System.IO e Microsoft.AspNetCore.Hosting:
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Blazor_DragDropUpload
@using Blazor_DragDropUpload.Shared
@using System.IO;
@using Microsoft.AspNetCore.Hosting;
|
A seguir abra o arquivo Index.razor e inclua o código abaixo:
@page "/"
@inject IWebHostEnvironment _env;
<h3>.NET 5.0 Blazor InputFile</h3>
<p>Usando o componente : <b>InputFile</b> </p>
<div>
<div class="inputArea">
<InputFile id="inputDefault"
OnChange="OnInputFileChange"
accept="image/png,image/gif,image/jpeg" />
</div>
<div class="dropArea @dropClass">
Arraste e solte seus arquivos aqui ou clique em Abrir Arquivos para abrir o diálogo...
<InputFile id="inputDrop"
OnChange="OnInputFileChange"
@ondragenter="HandleDragEnter"
@ondragleave="HandleDragLeave"
multiple />
</div>
@if (arquivos != null && arquivos.Count > 1)
{
<div>
<ul>
@foreach (var arquivo in arquivos)
{
<li>@arquivo.Name</li>
}
</ul>
</div>
}
@if (urls.Count > 0)
{
foreach (var url in urls)
{
<br />
<a href="@url" download>@url</a>
}
}
</div>
@code {
IReadOnlyList<IBrowserFile> arquivos;
List<string> urls = new List<string>();
string dropClass = string.Empty;
const int maxFileSize = 10485760;
private void HandleDragEnter()
{
dropClass = "dropAreaDrug";
}
private void HandleDragLeave()
{
dropClass = string.Empty;
}
async Task OnInputFileChange(InputFileChangeEventArgs e)
{
dropClass = string.Empty;
try
{
if (e.FileCount > 1)
{
arquivos = e.GetMultipleFiles();
urls.Clear();
urls.AddRange(await SalvarArquivos(arquivos));
}
else
{
arquivos = null;
var url = await SalvarArquivo(e.File);
urls.Clear();
urls.Add(url);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
throw;
}
}
private async Task<List<string>> SalvarArquivos(IReadOnlyList<IBrowserFile> arquivos)
{
var list = new List<string>();
var guid = Guid.NewGuid().ToString();
foreach (var file in arquivos)
{
var url = await SalvarArquivo(file, guid);
list.Add(url);
}
return list;
}
private async Task<string> SalvarArquivo(IBrowserFile file, string guid = null)
{
if (guid == null)
{
guid = Guid.NewGuid().ToString();
}
var relativePath = Path.Combine("uploads", guid);
var dirToSave = Path.Combine(_env.WebRootPath, relativePath);
var di = new DirectoryInfo(dirToSave);
if (!di.Exists)
{
di.Create();
}
var filePath = Path.Combine(dirToSave, file.Name);
using (var stream = file.OpenReadStream(maxFileSize))
{
using (var mstream = new MemoryStream())
{
await stream.CopyToAsync(mstream);
await File.WriteAllBytesAsync(filePath, mstream.ToArray());
}
}
var url = Path.Combine(relativePath, file.Name).Replace("\\", "/");
return url;
}
}
|
Vamos entender este código:
1- No código abaixo incluímos dois componentes InputFile. O primeiro atua como um InputFile normal e o seguinte permite realizar o drag and drop:
<div> <div class="inputArea"> <InputFile id="inputDefault" OnChange="OnInputFileChange" accept="image/png,image/gif,image/jpeg" /> </div> <div class="dropArea @dropClass"> Arraste e solte seus arquivos aqui ou clique em Abrir Arquivos para abrir o diálogo... <InputFile id="inputDrop" OnChange="OnInputFileChange" @ondragenter="HandleDragEnter" @ondragleave="HandleDragLeave" multiple /> </div> ....... |
O primeiro componente InputFile adicionado permite controlar os arquivos selecionados, o método OnInputFileChange () é atribuído ao evento OnChange. Esse método será declarado um pouco mais adiante na seção @code do Blazor. Além disso, este componente aceita apenas um único arquivo de imagem png, gif ou jpeg.
O segundo controle InputFile será usado para aceitar vários arquivos de qualquer tipo. Ele também usa o método OnInputFileChange() para lidar com os arquivos selecionados. Dois manipuladores adicionais de eventos @ondragenter e @ondragleave são usados para alterar o valor da variável dropClass que armazena o nome de uma classe CSS.
A seguir temos o código de marcação que é responsável por exibir os nomes dos arquivos a serem carregados. A lista de arquivos será definida na seção @code posteriormente :
@if (arquivos != null && arquivos.Count > 1)
{
<div>
<ul>
@foreach (var arquivo in arquivos)
{
<li>@arquivo.Name</li>
}
</ul>
</div>
}
|
E para concluir temos o código que exibe os links dos arquivos enviados. A lista da url será definida na seção @code a seguir :
@if (urls.Count > 0)
{
foreach (var url in urls)
{
<br />
<a href="@url" download>@url</a>
}
}
|
O código da seção @Code contém campos e métodos C# :
A lista de arquivos responsável por armazenar os arquivos para upload e a lista de urls responsável por armazenar os links para os arquivos enviados.
A variável dropClass captura o nome da classe CSS que é aplicada quando o usuário arrasta arquivos no segundo InputFile.
E a constante maxFileSize restringe o tamanho do arquivo único.
Os manipuladores
HandleDragEnter() e HandleDragLeave() que definem e
limpam o valor da variável dropClass.
O trabalho principal é feito dentro do manipulador
OnInputFileChange() que é responsável por salvar um ou vários arquivos
com o auxílio dos métodos privados SalvarArquivo() e
SalvarArquivos().
Os arquivos são armazenados no diretório wwwroot/upload. E em cada upload, uma nova pasta com um nome GUID exclusivo é criada dentro desse diretório.
Para concluir vamos incluir no arquivo CSS site.css dentro da pasta wwwroot/css o código abaixo que aplica um estilo ao controle usado para onde vamos arrastar os arquivos:
Executando o projeto teremos o resultado a seguir:
Pegue o projeto aqui: Blazor_DragDropUpload.zip (sem as referências)
"Porque a lei foi dada por Moisés;
a graça e a verdade vieram por Jesus Cristo."
João 1:17
ASP .NET Core - Iniciando com o Blazor
ASP .NET Core - CRUD usando Blazor e Entity ...
Blazor - O novo framework SPA da Microsoft -
Visual Studio Code - Suporte ao desenvolvimento Blazor