Hoje veremos como enviar arquivos para o servidor em uma aplicação Blazor WebAssembly usando o componente InputFile. |
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.
Continuando o artigo anterior vejamos agora como enviar arquivos usando o componente InputFile em uma aplicação Blazor com hospedagem WebAssembly.
Como vimos no artigo anterior, carregar e salvar arquivos em um aplicativo Blazor Server é relativamente simples. Seu código está sendo executado no servidor e você pode acessar facilmente o sistema de arquivos do servidor para salvar os arquivos carregados.
No entanto, um
aplicativo Blazor WebAssembly não pode fazer isso diretamente porque o código
está sendo executado dentro dos limites do navegador. Portanto, você precisa
fazer algum trabalho adicional para passar os arquivos do lado do cliente para o
servidor e salvá-los no servidor.
Vamos ver como isso pode ser feito na prática.
Recursos usados:
Blazor WebAssembly - Usando InputFile
Abra o VS 2022 Community e selecione a opção Create a New Project;
A seguir selecione a opção Blazor WebAssembly App e clique em next;
Informe o nome do projeto : BlazorWasmUpload;
A seguir define as configurações conforme a figura abaixo e clique em Create;
Observe que definimos a opção - ASP.NET Core hosted - assim teremos uma solução com 3 projetos: Client, Server, Shared.
Clicando no botão Create iremos obter a seguinte estrutura da solução:
Com o projeto criado vamos fazer as seguintes alterações, ajustes e configurações :
Exclua os arquivos abaixo e suas referências do projeto Client:
Exclua o controlador WeatherForecastController do projeto Server.
No arquivo _Imports.razor do projeto Client vamos incluir uma referência a :
@using System.Net.Http @using System.Net.Http.Json @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.JSInterop @using BlazorWasmUpload.Client @using BlazorWasmUpload.Client.Shared @using System.IO @using BlazorWasmUpload.Shared |
O primeiro permite acesso ao componente InptuFile e segundo permite criar e escrever em arquivos no servidor e o terceiro permite acesso a classe Arquivo que deverá ser criada no projeto Shared com o seguinte código:
namespace BlazorWasmUpload.Shared { public class Arquivo { public string? NomeArquivo { get; set; } public byte[]? ConteudoArquivo { get; set; } } } |
A seguir, no arquivo NavMenu.razor da pasta Shared inclua mais um item de menu para exibir a opção Upload:
... <div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <ul class="nav flex-column"> <li class="nav-item px-3"> <NavLink class="nav-link" href="/upload"> <span class="oi oi-cloud-upload" aria-hidden="true"></span> Upload </NavLink> </li> </ul> </div> ... |
Crie uma pasta images dentro de wwwroot e inclua nesta pasta a imagem upload1.jpg que iremos usar no projeto.
A seguir altere o código do arquivo Index.razor para:
@page "/" <PageTitle>Index</PageTitle> <img src="/images/upload1.jpg" /> <h3>Blazor Server - InputFile</h3> |
A seguir vamos criar um novo componente chamado FileUpload na pasta Pages do projeto Cliente e incluir o código abaixo neste arquivo:
@page "/upload" @inject HttpClient Http <h2>Blazor WebAssembly - Upload</h2> <h3>@Message</h3> <form @onsubmit="OnSubmit"> @code { private void OnInputFileChange(InputFileChangeEventArgs e) private async void OnSubmit() Arquivo Arquivo = new Arquivo(); await Http.PostAsJsonAsync<Arquivo>("/api/fileupload", Arquivo); |
Vamos entender o código :
1- Injetamos uma instância de HttpClient para
@inject HttpClient Http
2- A propriedade
Message apenas exibe mensagens:
<h5>@Message</h5>
3- Criamos um formulário que será submetido no evento OnSubmit onde estamos usando o componente InputFile usando o atributo multiple que permite selecionar mais de um arquivo, e que define o método OnInputFileChange onde vamos tratar a exibição de quantos arquivos foram selecionados.
<form @onsubmit="OnSubmit">
<InputFile OnChange="OnInputFileChange"
multiple />
<br /><br />
<button type="submit">Enviar Arquivo(s) selecionado(s) para
Upload</button>
</form>
O botão Enviar apenas submete o formulário.
No bloco de código do arquivo temos:
4- A definição do texto da mensagem inicial e a definição da variável arquivoSelecionados como sendo uma lista somente leitura do tipo IBrowserFile que representa os dados de um arquivo selecionado pelo InputFile :
string Message =
"Nenhum arquivo selecionado";
IReadOnlyList<IBrowserFile> arquivoSelecionados;
5- O método OnInputFileChange trata o evento OnChange do componente InputFile e obtém a lista de arquivos selecionados alterando o texto da mensagem:
private
void OnInputFileChange(InputFileChangeEventArgs
e)
{
arquivoSelecionados = e.GetMultipleFiles();
Message = $"{arquivoSelecionados.Count}
arquivo(s) selecionado(s)";
}
6- No método assíncrono OnSubmit estamos tratando o envio do formulário.
Primeiro
verificamos se existem arquivos selecionados para a seguir percorrer a lista de
arquivos usando um bloco foreach e ler cada arquivo
e a seguir usamos o método OpenReadStream() para
abrir um fluxo através do qual o conteúdo do arquivo carregado pode ser lido e a
seguir copiamos o arquivo para a memória usando o
método CopyToAsync().
Como queremos salvar o arquivo carregado no servidor criamos uma nova instância
do arquivo e atribuímos o nome e a seguir o conteúdo do arquivo que foi copiado
para a memória, e, a seguir usamos a instância de
HttpClient para postar o arquivo para o servidor usando o endpoint
/api/fileupload/ e passando o arquivo selecionado:
private async void OnSubmit() { foreach (var file in arquivosSelecionados) { Stream stream = file.OpenReadStream(); MemoryStream ms = new MemoryStream(); await stream.CopyToAsync(ms); stream.Close();
Arquivo Arquivo = new Arquivo(); await Http.PostAsJsonAsync<Arquivo>("/api/fileupload", Arquivo); |
Atenção !!! Os arquivos enviados estão sendo salvos na pasta Uploads que deverá ser criada dentro da pasta wwwroot no projeto Server.
Agora vamos definir o código do controlador FileUploadController no projeto Server que vai receber o arquivo e escrever o arquivo no local indicado.
using BlazorWasmUpload.Shared; using Microsoft.AspNetCore.Mvc;
namespace BlazorWasmUpload.Server.Controllers
[HttpPost] |
Agora é só alegria...
Executando o projeto teremos o resultado abaixo:
Podemos melhorar a implementação feita neste exemplo em diversos aspectos como definindo um tamanho limite para envio dos arquivos e implementar um tratamento de erros mais robusto.
Pegue o projeto aqui: BlazorWasmUpload.zip (sem as referências)
"Porque, se vivemos, para o Senhor vivemos; se
morremos, para o Senhor morremos. De sorte que, ou
vivamos ou morramos, somos do Senhor."
Romanos 14:8
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
Vale a pena usar o Blazor
Blazor - Usando o recurso da Virtualização (.NET 5)
Blazor - Conceitos, dicas e truques valiosos - I