Oi pessoal!
Nesse vou mostrar como manipular arquivos do azure storage com c#, e ainda fornecer um exemplo de como a aplicar em um aplicativo angular.
Você precisa ter instalado em sua máquina:
e também uma assinatura no Azure
Move Storage
O move storage é um aplicativo angular com uma interface amigável para fazer as operações que serão demonstradas nesse artigo.
Tanto a api quanto o app estão no mesmo repositório.
As operações que vamos ver são:
- Criar um container
- Listar containers
- Deletar container
- Listar arquivos em um container
- Fazer upload de um ou mais arquivos
- Fazer download de um arquivo
- Deletar um arquivo de um container
- Mover arquivo de um container para outro
Faça uma pré-visualização do projeto:
Faça clone ou dê uma espiada no código do projeto:
Navegue no terminal até a pasta raiz do projeto onde se encontra o Readme.md
Azure
Faça login na sua conta do azure e defina uma conta padrão para esse tutorial, assim você garante que a operação será feita no tenant correto:
az login
az account set --subscription <subscriptionid>
Vamos definir algumas variáveis no terminal, para facilitar a escrita dos demais comandos
substitua o <nome exclusivo do storage> por por exemplo:
storagelsv1990, na qual a primeira parte é o nome do app, e a segunda parte são as iniciais do seu nome seguido do ano em que nasceu, (Lucas Silvério Vargas, 1990 - lsv1990).
essa é só uma dica para dar um nome ao storage, que deve ser exclusivo.
$group="MoveStorage"
$storageName="<nome exlusivo do app>"
Agora vamos criar um grupo de recursos e criar o nosso storage
az group create -n $group -l eastus2
az storage account create -n $storageName -g $group -l eastus2 --sku Standard_LRS
Obtenha a string de conexão e guarde, vamos utilizar mais adiante no nosso aplicativo:
az storage account show-connection-string -g $group -n $storageName
Agora crie um container e vamos subir alguns arquivos de exemplo:
az storage container create -n container1 --account-name $storageName
az storage blob upload-batch -d container1 -s .\documents\ --account-name $storageName
Aplicativo
No terminal navegue até o aplicativo angular e levante o servidor.
cd .\src\app\
npm i
ng s -o
Em outra aba do terminal navegue até a api e levante a aplicação dotnet.
cd .\src\api\
dotnet run
Adicione uma conexão ao storage, vamos colar a connection string que obtivemos anteriormente e informar um apelido para essa instância de gerenciamento:
Selecione o container1 e será carregado e os arquivos serão listados:
Crie uma nova instância de gerenciamento com a mesma connection string e vamos criar um novo container pelo próprio aplicativo:
O nome pode conter apenas letras minúsculas, números e hifens e deve começar com uma letra ou com um número. Cada hífen deve ser precedido e seguido por um caractere que não seja um hífen. O nome também deve ter entre 3 e 63 caracteres.
Selecione um arquivo e arraste para área de arquivos do container2, e o arquivo será copiado de um container para o outro:
Também é possível mover entre storages diferentes.
No repositório você consegue ver como construí essa dinâmica no front-end, mas nesse artigo vou explanar apenas os métodos em c#.
WebApi
Disclaimer
Essa é uma aplicação para fins didáticos, nela eu passo as connection strings de alguns métodos pelos parâmetros da url. Em produção não fazemos assim, connection strings são informados em arquivos de configuração como o appsettings.json.
O método DecodeUrl é usado para fazer o decode da connection string e um tratamento para sinais de "+" que as mesmas podem possuir
private static string DecodeUrl(string connectionString) => HttpUtility.UrlDecode(connectionString).Replace(" ", "+");
Leia mais sobre isso aqui.
Comandos
Os comandos foram declarados como Records para diminuir a escrita de código e também estão no arquivo de controller, devido a natureza simples desse projeto:
public record StorageConnection(string ConnectionString, string Alias);
public record Container(string Name, StorageConnection Connection);
public record FileConvert(string Name, string Base64);
public record Upload(Container Container, List<FileConvert> FilesBase64);
public record MoveFile(Container From, Container To, string File);
public record NewContainer(string ConnectionString, string ContainerName);
Criar um novo container
[HttpPost("container")]
public ActionResult AddContainer(NewContainer container)
{
var storage = new BlobServiceClient(container.ConnectionString);
storage.CreateBlobContainer(container.ContainerName);
return Created("", new { response = "Arquivo transferido" });
}
Listar containers
[HttpGet("containers/{connectionString}")]
public ActionResult GetContainers(string connectionString)
{
var storage = new BlobServiceClient(DecodeUrl(connectionString));
var response = storage.GetBlobContainers().Select(x => x.Name);
return Ok(response);
}
Deletar um container
[HttpDelete("container/{connectionString}/{containerName}")]
public ActionResult RemoveContainer(string connectionString, string containerName)
{
var blob = new BlobContainerClient(DecodeUrl(connectionString), containerName);
blob.Delete();
return NoContent();
}
Listar arquivos de um container
[HttpGet("files/{connectionString}/{containerName}")]
public ActionResult GetFiles(string connectionString, string containerName)
{
var container = new BlobContainerClient(DecodeUrl(connectionString), containerName);
var response = container.GetBlobs().Select(x => x.Name);
return Ok(response);
}
Deletar um arquivo
[HttpDelete("file/{connectionString}/{containerName}/{fileName}")]
public ActionResult RemoveFile(string connectionString, string containerName, string fileName)
{
var blob = new BlobClient(DecodeUrl(connectionString), containerName, fileName);
blob.Delete();
return NoContent();
}
Upload de arquivos
[HttpPost("upload")]
public ActionResult Upload(Upload upload)
{
var container = new BlobContainerClient(upload.Container.Connection.ConnectionString, upload.Container.Name);
foreach (var file in upload.FilesBase64)
{
var data = file.Base64.Substring(file.Base64.IndexOf(",") + 1);
container.UploadBlob(file.Name, new MemoryStream(Convert.FromBase64String(data)));
}
return Created("", new { response = "Arquivos enviados" });
}
Download de um arquivo
[HttpGet("download/{connectionString}/{containerName}/{fileName}")]
public async Task<ActionResult> DownloadFile(string connectionString, string containerName, string fileName)
{
var blob = new BlobClient(DecodeUrl(connectionString), containerName, fileName);
BlobProperties properties = await blob.GetPropertiesAsync();
var result = await blob.DownloadContentAsync();
return File(result.Value.Content.ToArray(), properties.ContentType, "");
}
Mover um arquivo de um storage/container para outro storage/container
[HttpPost("move")]
public async Task<ActionResult> MoveFile(MoveFile moveFile)
{
BlobContainerClient sourceContainer = new(DecodeUrl(moveFile.From.Connection.ConnectionString), moveFile.From.Name);
BlobContainerClient destContainer = new(moveFile.To.Connection.ConnectionString, moveFile.To.Name);
BlobClient destBlob = destContainer.GetBlobClient(moveFile.File);
await destBlob.StartCopyFromUriAsync(GetSharedAccessUri(moveFile.File, sourceContainer));
await sourceContainer.DeleteBlobAsync(moveFile.File);
return Created("", new { response = "Arquivo transferido" });
}
private static Uri GetSharedAccessUri(string blobName, BlobContainerClient container)
{
DateTimeOffset expiredOn = DateTimeOffset.UtcNow.AddMinutes(60);
BlobClient blob = container.GetBlobClient(blobName);
Uri sasUri = blob.GenerateSasUri(BlobSasPermissions.Read, expiredOn);
return sasUri;
}
Veja mais sobre o método de cópia e os motivos de gerar uma UriSaS aqui
Espero que isso te ajude!
Top comments (0)