Leobreda.net

Web, .Net,
SQL, Cloud...

Trabalhando com Amazon Web Services S3

Criando Buckets, pastas, upload e download de arquivos via .Net Framework

Ter uma interface em sua aplicação (seja web ou desktop) que possibilita o armazenamento de arquivos na AWS S3, se torna mais usual (e seguro) do que gerenciar usuários via IAM e disponibilizar acessos ao console.aws.
Em resumo... os usuários acessam a sua aplicação, e a sua aplicação que acessa o S3.

Sendo assim, criaremos um console em .Net Framework (ou .Net core), na qual irá:

  1. Criar 5 arquivos no diretório Documentos no Windows
  2. Instanciar conexão ao S3
  3. Criar 1 Bucket
  4. Realizar o upload dos arquivos
  5. Listar todos os Buckets criados
  6. Listar arquivos do Bucket
  7. Fazer o download do arquivo, e acessando via URL

Código-fonte:

using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.SecurityToken;
using System.Diagnostics;


namespace ConsoleAws
{
    class Program
    {
        private static string DIRETORIO_DOCUMENTOS =
            Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
            + @"\Documents\";


        private static string CHAVE_ACESSO = "COLOQUE O SEU ACCESS KEY AQUI";
        private static string CHAVE_ACESSO_SECRETA = "COLOQUE A SUA SECRET KEY AQUI";


        private static RegionEndpoint REGION = RegionEndpoint.SAEast1;
        private List<string> Arquivos { get; set; }
        private AmazonS3Client Client { get; set; }
        private string Bucket { get; set; }


        static void Main(string[] args)
        {
            Program program = new Program();
            program.Inicializar();
        }


        private void Inicializar()
        {
            this.CriarArquivos();
            this.Conectar();
            this.CriarBucket();
            this.Upload();
            this.ListarBuckets();
        }


        /// <summary>
        /// Faz a criação de 5 arquivos no diretório Documentos do usuário
        /// </summary>
        /// <returns></returns>
        private void CriarArquivos()
        {
            Console.WriteLine("Criando os arquivos abaixo no diretório "
             + DIRETORIO_DOCUMENTOS + "...");

            string[] rand = { "gato", "cachorro", "macaco", "tartaruga", "canario" };
            string arquivo = null;
            this.Arquivos = new List<string>();


            for (int i = 0; i < 5; i++)
            {
                arquivo = rand[i] + "teste-amazon-s3.txt";
                Console.Write(arquivo);
                File.WriteAllText(DIRETORIO_DOCUMENTOS + arquivo, 
                "Exemplo de arquivo armazenado na Amazon S3");

                Arquivos.Add(arquivo);
                Thread.Sleep(500);
                Console.WriteLine("\t\tSucesso!");
            }
            Thread.Sleep(2000);
        }


        private void Conectar()
        {
            Console.WriteLine("\n\nConectando ao Amazon S3...");
            Thread.Sleep(2000);

            BasicAWSCredentials credentials = new BasicAWSCredentials(CHAVE_ACESSO,
            CHAVE_ACESSO_SECRETA);

            this.Client = new AmazonS3Client(credentials, REGION);
            Console.WriteLine("Conexão realizada com sucesso!");
            Thread.Sleep(3000);
        }


        private void CriarBucket()
        {
            this.Bucket = "meu-bucket" + DateTime.Now.ToString("yyyyMMddHHmmss");
            Console.WriteLine("\n\nCriando o bucket " + this.Bucket + "...");
            Thread.Sleep(2000);

            PutBucketRequest request = new PutBucketRequest();
            request.CannedACL = S3CannedACL.Private;
            PutBucketResponse response = new PutBucketResponse();
            request.BucketName = this.Bucket;

            response = Client.PutBucket(request);

            Console.WriteLine("Bucket criado com sucesso!");
            Thread.Sleep(2000);
        }




        private void Upload()
        {
            Console.WriteLine("\n\nEfetuando o upload dos arquivos abaixo...");
            Thread.Sleep(2000);


            for (int i = 0; i < Arquivos.Count; i++)
            {
                UploadPartRequest request = new UploadPartRequest
                {
                    BucketName = this.Bucket,
                    FilePath = DIRETORIO_DOCUMENTOS + Arquivos[i],
                    Key = Arquivos[i].Substring(0, 1) + "/" + Arquivos[i]
                };


                Console.Write(Arquivos[i]);
                UploadPartResponse response = this.Client.UploadPart(request);


                //Habilita o acesso do arquivo via url
                this.Client.PutACL(new PutACLRequest
                {
                    BucketName = this.Bucket,
                    Key = Arquivos[i].Substring(0, 1) + "/" + Arquivos[i],
                    CannedACL = S3CannedACL.PublicRead
                });


                Console.WriteLine("\t\tSucesso!");
                Thread.Sleep(500);
            }
            Thread.Sleep(2500);
        }




        private void ListarBuckets()
        {
            Console.WriteLine("\n\nRecuperando a lista de Buckets ...");
            Thread.Sleep(1000);


            ListBucketsResponse response = null;
            response = Client.ListBuckets();


            int i = 1;
            foreach (S3Bucket bucket in response.Buckets)
            {
                Console.WriteLine("# " + i + "\t" + bucket.BucketName);
                i++;
            }


            try
            {
                Console.Write("Informe o ID do Bucket que deseja listar os arquivos: ");
                Thread.Sleep(500);
                
                int id = Convert.ToInt32(Console.ReadLine());
                this.ListarArquivos(response.Buckets[id - 1].BucketName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ID inválido:");
                Thread.Sleep(500);
                this.ListarBuckets();
                return;
            }
        }


        private void ListarArquivos(string bucket)
        {
            Console.WriteLine("\n\nListando arquivos do Bucket " + bucket + "...");
            Thread.Sleep(2000);


            ListObjectsRequest request = new ListObjectsRequest();
            request.BucketName = bucket;


            ListObjectsResponse response = Client.ListObjects(request);


            int i = 1;
            foreach (S3Object obj in response.S3Objects)
            {
                Console.WriteLine("# " + i + "\t" + obj.Key);
                i++;
            }


            Console.Write("Informe o ID do arquivo que deseja acessar: ");


            try
            {
                int id = Convert.ToInt32(Console.ReadLine());
                this.AcessarArquivo(response.S3Objects[id - 1]);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ID inválido:");
                Thread.Sleep(500);
                this.ListarArquivos(bucket);
                return;
            }
        }


        private void AcessarArquivo(S3Object obj)
        {
            Console.WriteLine("\n\nComo deseja abrir o arquivo " + obj.Key + " ?");
            Console.WriteLine("# 1 \t Download");
            Console.WriteLine("# 2 \t Abrir no navegador");
            
            try
            {
                int id = Convert.ToInt32(Console.ReadLine());


                if (id.Equals(1))
                    this.Download(obj);


                else if (id.Equals(2))
                    this.Navegar(obj);


                else
                    throw new Exception();
            }
            catch
            {
                Console.WriteLine("Opção inválida:");
                Thread.Sleep(500);
                this.AcessarArquivo(obj);
                return;
            }
        }


        private void Download(S3Object obj)
        {
            Console.WriteLine("\n\nEfetuando o download do arquivo " + obj.Key);
            GetObjectRequest objectRequest = new GetObjectRequest();
            objectRequest.BucketName = obj.BucketName;
            objectRequest.Key = obj.Key;
            GetObjectResponse objectResponse = Client.GetObject(objectRequest);
            objectResponse.WriteResponseStreamToFile(DIRETORIO_DOCUMENTOS 
            + @"download-" + obj.Key);

            Process.Start(DIRETORIO_DOCUMENTOS + @"download-" + obj.Key);
            this.ListarBuckets();
        }


        private void Navegar(S3Object obj)
        {
            Console.WriteLine("\n\nAbrindo o arquivo " + obj.Key + " no navegador...");
            string url = string.Format("https://{0}.s3-{1}.amazonaws.com/{2}",
                            obj.BucketName, REGION.SystemName, obj.Key);
            Process.Start(url);
            this.ListarBuckets();
        }
    }
}

Ao compilar o e executar o código acima, deverá exibir um console interativo conforme imagens abaixo. No final do console, você poderá fazer o download do arquivo bem como acessá-lo no navegador.

Cada vez que o console é executado, um novo Bucket é criado.

Acessando o último Bucket, podemos visualizar as pastas criadas, e dentro de cada pasta os respectivos arquivos.

Voltando ao console, na opção "Abrir no navegador", você será direcionado para o arquivo via URL.


NOTAS

Dependências / usings

É normal que na primeira compilação apresente diversos erros de referências (using Amazon...).

using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.SecurityToken;

Para corrigir, refaça as referências via NuGet das seguintes bibliotecas:


Autenticação

As variáveis estáticas CHAVE_ACESSO e CHAVE_ACESSO_SECRETA representam as suas credenciais de segurança (IAM). É uma combinação dos 2 valores para realizar a autenticação de modo seguro.

static string CHAVE_ACESSO = "ABCDEFGHIJKLMNOPQRBRA";
static string CHAVE_ACESSO_SECRETA = "52aac6e452aaf1f5l0PnId7IJn+A2B";   

Tais chaves podem ser geradas e consultadas na rota Serviços > IAM > Gerenciar Credenciais de Segurança


Região

Os Buckets foram criados na região America do Sul (São Paulo). Você poderá realizar a troca para a região desejada alterando na variável estática REGION.

static RegionEndpoint REGION = RegionEndpoint.SAEast1;

Acesso público

Os arquivos podem ser carregados na internet por qualquer pessoa que tenha a URL em mãos, representando um alto risco de segurança para informações confidenciais.

Caso queira bloquear este acesso público, comente toda a chamada do método PutACL() abaixo.

this.Client.PutACL(new PutACLRequest
{
    BucketName = this.Bucket,
    Key = Arquivos[i].Substring(0, 1) + "/" + Arquivos[i],
    CannedACL = S3CannedACL.PublicRead
});

E assim o acesso aos arquivos via URL será bloqueado.

Enfim, o código apresentado neste artigo dá um norte em cenários onde possibilita realizar as operações básicas na AWS S3. Existem muito mais funcionalidades que podem ser exploradas no link abaixo:

https://docs.aws.amazon.com/pt_br/AmazonS3/latest/dev/create-bucket-get-location-example.html#create-bucket-get-location-dotnet




Acessar todos os artigos »