Introducción a S3 y almacenamiento en la nube para desarrolladores .NET
Los almacenes de objetos en la nube compatibles con el protocolo Amazon S3 (Simple Storage Service) se han convertido en el estándar de facto para almacenar datos no estructurados: imágenes, videos, copias de seguridad, registros y artefactos de compilación. En el ecosistema C# (.NET), el trabajo con dichos almacenes se implementa a través del AWS SDK oficial para .NET o mediante clientes ligeros para soluciones compatibles con S3 (MinIO, Yandex Object Storage, DigitalOcean Spaces).
En este artículo, analizaremos las operaciones principales: conexión, creación de un bucket, carga, descarga y eliminación de objetos. Todos los ejemplos están escritos en C# utilizando .NET 8.
Instalación de la librería AWS SDK para .NET
Para trabajar con S3 desde C#, es necesario instalar el paquete NuGet AWS SDK for .NET — S3:
dotnet add package AWSSDK.S3dotnet add package AWSSDK.Extensions.NETCore.Setup // para integración DISi utiliza MinIO u otros almacenes compatibles con S3 (no AWS), el mismo paquete es suficiente: admite endpoints personalizados.
Configuración básica del cliente S3
Creemos un cliente para trabajar con S3. En el siguiente ejemplo se utiliza MinIO, ejecutado localmente en el puerto 9000:
using Amazon;using Amazon.S3;using Amazon.Runtime;
var config = new AmazonS3Config{ ServiceURL = "http://localhost:9000", // para MinIO u otro almacén compatible con S3 ForcePathStyle = true, // obligatorio para MinIO UseHttp = true};
var credentials = new BasicAWSCredentials("minioadmin", "minioadmin");var s3Client = new AmazonS3Client(credentials, config);Para AWS S3, basta con especificar la región y usar las credenciales estándar:
var s3Client = new AmazonS3Client(RegionEndpoint.EUWest1);Creación y eliminación de un bucket
Creación de un bucket
public async Task CreateBucketAsync(string bucketName){ var putBucketRequest = new PutBucketRequest { BucketName = bucketName, UseClientRegion = true }; var response = await s3Client.PutBucketAsync(putBucketRequest); Console.WriteLine($"Bucket {bucketName} creado. Estado HTTP: {response.HttpStatusCode}");}Verificación de existencia del bucket
public async Task<bool> DoesBucketExistAsync(string bucketName){ return await AmazonS3Util.DoesS3BucketExistAsync(s3Client, bucketName);}Eliminación de un bucket
public async Task DeleteBucketAsync(string bucketName){ await s3Client.DeleteBucketAsync(bucketName); Console.WriteLine($"Bucket {bucketName} eliminado.");}Carga de archivos (Upload)
El escenario más común es la carga de un archivo en un bucket. Usamos PutObjectAsync:
public async Task UploadFileAsync(string bucketName, string key, string filePath){ var putRequest = new PutObjectRequest { BucketName = bucketName, Key = key, FilePath = filePath, ContentType = "application/octet-stream" };
var response = await s3Client.PutObjectAsync(putRequest); Console.WriteLine($"Archivo {key} cargado. ETag: {response.ETag}");}Carga desde un stream — útil para archivos recibidos del usuario a través de un formulario web:
public async Task UploadFromStreamAsync(string bucketName, string key, Stream inputStream){ var putRequest = new PutObjectRequest { BucketName = bucketName, Key = key, InputStream = inputStream }; await s3Client.PutObjectAsync(putRequest);}Descarga de archivos (Download)
Se puede descargar un objeto a un archivo o a un stream:
public async Task DownloadFileAsync(string bucketName, string key, string downloadPath){