Carregando arquivos para o Azure Blob Storage no Blazor

· 6 min de leitura

O serviço de armazenamento Azure Blob é um dos serviços mais utilizados no ecossistema Azure, permite fazer upload de muitos arquivos para a nuvem e é super barato. Também possui um site intuitivo onde você pode acessá-los ou baixá-los por um link direto.

No geral, é um serviço muito bom, tenho usado tanto para projetos profissionais quanto pessoais e, honestamente, o melhor é a simplicidade de como fazê-lo funcionar.

A maioria dos casos que usei o Azure Blob Storage está no backend, carregando diretamente algo que é resultado de uma operação ou algo assim. Então, eu realmente não fiz nenhum tipo de upload de um arquivo de um site ou algo assim. Azarado!

Como sou fã do Blazor, estou apresentando uma maneira de fazer upload de arquivos para um armazenamento de Blob do Azure usando a entrada de arquivo nativa do HTML5.

Pré-requisitos

  • Conta Azure (se você não tiver, vá aqui com um monte de $$$).
  • Um IDE (VS, Código, qualquer um funcionará)
  • .NET Core 3.0 ou superior

Criando um Armazenamento de Blobs do Azure

Vá para o seu portal do Azure e vamos criar uma conta de armazenamento.

Primeiro pesquise por Storage accounts e clique no resultado.

Após carregar, clique em Create.

Um formulário aparecerá com várias etapas, então vá em frente e preencha-as.

Após preencher tudo com as configurações desejadas, passe na validação e crie o recurso.

Depois de criado, clique em Go to resource. Obteremos uma string de conexão que nos permitirá brincar com a API.

Obtenha as chaves de recursos

Depois de chegarmos ao nosso recurso recém-criado, vá para Acccess keys em Security + networking. Após carregar você verá um Connection string e Key, copie-os porque precisaremos deles mais tarde!

Criando um projeto legal do Blazor Server

Vou usar o Visual Studio 2022 para este tutorial, mas como disse antes, você pode usar qualquer outro IDE e apenas criar o projeto usando a CLI dotnet.

Então, vamos criar um projeto Blazor bem rápido usando o Visual Studio em apenas algumas etapas.

Se executarmos o que acabamos de criar, ficará assim, apenas um aplicativo Blazor normal e simples.

Agora que criamos o projeto, vamos fazer algumas coisas de UI para termos uma nova página com um monte de entradas para que possamos preencher com as chaves do recurso, um InputFile para o(s) arquivo(s), um botão para fazer algo e uma mensagem que resultará da ação.

Criando o modelo

Precisaremos de alguns modelos para fazer isso corretamente. Primeiro teremos a classe BlobRequest que tratará a string de conexão, o nome do contêiner e os arquivos.

Além disso, para manter tudo organizado, criaremos uma classe chamada BlobFile na qual armazenaremos o Name e o Data.

Criei uma pasta chamada Models então temos tudo separado.

As aulas são muito simples.```csharp using System.ComponentModel.DataAnnotations;

namespace UploadingFilesAzBlobBlazor.Models { public class BlobRequest { [Required(ErrorMessage = “Connection string is required”)] public string? ConnectionString { get; set; } [Required(ErrorMessage = “Container name is required”)] public string? Container { get; set; } public List? Files { get; set; } } }


```csharp
namespace UploadingFilesAzBlobBlazor.Models
{
    public class BlobFile
    {
        public string? Name { get; set; }
        public byte[]? Data { get; set; }
    }
}

Modificando a IU

Agora que criamos nosso modelo, vamos em frente e fazer mágica na UI com ele!

Primeiro de tudo, crie uma página na pasta Pages chamada Upload.razor.

Nesta página vamos adicionar um pequeno formulário que preencherá nossa classe BlobRequest, então temos que adicionar entradas para ConnectionString, Container e Files.

@page "/upload"
@using UploadingFilesAzBlobBlazor.Models
@inject IJSRuntime JsRuntime
<PageTitle> Upload</PageTitle>

<h1> Azure blob storage uploader!</h1>

<EditForm Model="@modal" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />

<div class="mb-3">
<label for="connectionString" class="form-label"> Connection string</label>
<InputText class="form-control" id="connectionString" @bind-Value="modal.ConnectionString" />
</div>

<div class="mb-3">
<label for="container" class="form-label"> Container name</label>
<InputText class="form-control" id="container" @bind-Value="modal.Container" />
</div>

<div class="mb-3">
<label for="formFileMultiple" class="form-label"> Files</label>
<InputFile OnChange="OnInputFileChange" class="form-control" id="formFileMultiple" multiple />
</div>

<div class="mb-3">
<button type="submit" class="btn btn-primary"> Submit</button>
</div>
</EditForm>

@code {
    private BlobRequest modal = new();
    private EditContext editContext;
    IReadOnlyList <IBrowserFile> selectedFiles;
    private void OnInputFileChange(InputFileChangeEventArgs e)
    {
        selectedFiles = e.GetMultipleFiles();
        this .StateHasChanged();
    }

    private async Task HandleValidSubmit() {
        // This is where we are going to upload stuff ! 
        await JsRuntime.InvokeVoidAsync("alert", "Files uploaded!");
    }
}

É um pouco de código, mas basicamente renderizará o formulário e tratará da validação.

Se você pressionar o botão para fazer upload e estiver tudo bem, será exibido um alerta.

Fazendo upload para o Armazenamento de Blobs do Azure

Agora que concluímos a maior parte da interface do usuário, vamos instalar o pacote que manipulará a API do Azure Blob Storage e nos permitirá fazer upload de arquivos. Muito simples.

Adicione o pacote NuGet

Vamos gerenciar os pacotes NuGet do projeto e adicionar Azure.Storage.Blob.

Carregar para Azure Blob Stoare

Agora vamos fazer a lógica para realmente fazer o upload do arquivo, normalmente usaríamos a string de conexão e a chave do app.config, mas para o propósito deste tutorial, usamos entradas e fornecemos os dados lá.

Primeiro, vamos adicionar o using para a classe Azure Blob Storage

@using Azure.Storage.Blobs
@using Azure.Storage.Blobs.Models

Então vamos trabalhar no método HandleValidSubmit, que vai se conectar ao armazenamento de blob, criar o contêiner se ele não existir e depois fazer upload dos arquivos.

private async Task HandleValidSubmit()
{
    try
    {
        // Instantiate container
        var container = new BlobContainerClient(modal.ConnectionString, modal.Container);
        // Create container if not exists
        var createResponse = await container.CreateIfNotExistsAsync();
        // Set access policy
        if (createResponse != null && createResponse.GetRawResponse().Status == 201)
        {
            await container.SetAccessPolicyAsync(Azure.Storage.Blobs.Models.PublicAccessType.Blob);
        }

        // For each file that we have uploaded
        foreach (var file in selectedFiles)
        {
            // New blob
            var blob = container.GetBlobClient(file.Name);
            // Delete any blob with the same name
            await blob.DeleteIfExistsAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots);
            // Create a file stream and use the UploadSync method to upload the Blob.
            using (var fileStream = file.OpenReadStream())
            {
                await blob.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = file.ContentType });
            }
        }

        // Display success message
        await JsRuntime.InvokeVoidAsync("alert", "Files uploaded!");
    }
    catch (Exception e)
    {
        // Display error message
        await JsRuntime.InvokeVoidAsync("alert", "An error ocurred!");
    }
}

Testando o código

Agora é hora de testar o código, para isso basta preencher o formulário e clicar em enviar.

Iremos exibir um alerta e o arquivo deverá ser carregado no Azure Blob Storage, acesse o Portal do Azure e dê uma olhada.

Como você pode ver, o container também foi criado, agora se entrarmos no container, vemos o arquivo que carregamos.

Bom trabalho!

Refatorar

Agora que tudo funcionou, vamos mover o código da página .razor para uma classe .razor.cs para que fique melhor.

Se você estiver usando o Visual Studio 2022, há uma lâmpada quando você passa o mouse no @code, ele mostrará uma opção para Extract block to code behind, e fará o que diz!

Agora você vai ter tudo separado e pronto!

Código

Todo esse projeto está no Github e você pode encontrá-lo aqui!

Se você tiver qualquer problema ou dúvida, sinta-se à vontade para entrar em contato comigo em qualquer mídia social em @emimontesdeoca (no Twitter na verdade é @emimontesdeocaa com dois aa no final). Você também pode encontrar a maioria das minhas redes sociais no cabeçalho do blog.

Espero que você tenha gostado da postagem! Cia!

Recursos