Введение в S3 и облачные хранилища для .NET-разработчика
Облачные объектные хранилища, совместимые с протоколом Amazon S3 (Simple Storage Service), стали стандартом де-факто для хранения неструктурированных данных: изображений, видео, бэкапов, логов и артефактов сборки. В экосистеме C# (.NET) работа с такими хранилищами реализуется через официальный AWS SDK для .NET или через легковесные клиенты для S3-совместимых решений (MinIO, Yandex Object Storage, DigitalOcean Spaces).
В этой статье мы разберём основные операции: подключение, создание бакета, загрузку, скачивание и удаление объектов. Все примеры написаны на C# с использованием .NET 8.
Установка библиотеки AWS SDK для .NET
Для работы с S3 из C# необходимо установить NuGet-пакет AWS SDK for .NET — S3:
dotnet add package AWSSDK.S3
dotnet add package AWSSDK.Extensions.NETCore.Setup // для DI-интеграции
Если вы используете MinIO или другие S3-совместимые хранилища (не AWS), достаточно того же пакета — он поддерживает кастомные endpoint'ы.
Базовая настройка S3-клиента
Создадим клиент для работы с S3. В примере ниже используется MinIO, запущенный локально на порту 9000:
using Amazon;
using Amazon.S3;
using Amazon.Runtime;
var config = new AmazonS3Config
{
ServiceURL = "http://localhost:9000", // для MinIO или другого S3-совместимого хранилища
ForcePathStyle = true, // обязательно для MinIO
UseHttp = true
};
var credentials = new BasicAWSCredentials("minioadmin", "minioadmin");
var s3Client = new AmazonS3Client(credentials, config);
Для AWS S3 достаточно указать регион и использовать стандартные credentials:
var s3Client = new AmazonS3Client(RegionEndpoint.EUWest1);
Создание и удаление бакета (bucket)
Создание бакета
public async Task CreateBucketAsync(string bucketName)
{
var putBucketRequest = new PutBucketRequest
{
BucketName = bucketName,
UseClientRegion = true
};
var response = await s3Client.PutBucketAsync(putBucketRequest);
Console.WriteLine($"Бакет {bucketName} создан. HTTP статус: {response.HttpStatusCode}");
}
Проверка существования бакета
public async Task<bool> DoesBucketExistAsync(string bucketName)
{
return await AmazonS3Util.DoesS3BucketExistAsync(s3Client, bucketName);
}
Удаление бакета
public async Task DeleteBucketAsync(string bucketName)
{
await s3Client.DeleteBucketAsync(bucketName);
Console.WriteLine($"Бакет {bucketName} удалён.");
}
Загрузка файлов (Upload)
Самый распространённый сценарий — загрузка файла в бакет. Используем 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($"Файл {key} загружен. ETag: {response.ETag}");
}
Загрузка из потока (stream) — полезно для файлов, полученных от пользователя через веб-форму:
public async Task UploadFromStreamAsync(string bucketName, string key, Stream inputStream)
{
var putRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
InputStream = inputStream
};
await s3Client.PutObjectAsync(putRequest);
}
Скачивание файлов (Download)
Скачать объект можно в файл или в поток:
public async Task DownloadFileAsync(string bucketName, string key, string downloadPath)
{
var getRequest = new GetObjectRequest
{
BucketName = bucketName,
Key = key
};
using var response = await s3Client.GetObjectAsync(getRequest);
await response.WriteResponseStreamToFileAsync(downloadPath, false, CancellationToken.None);
Console.WriteLine($"Файл {key} скачан в {downloadPath}");
}
Получение объекта в виде потока для дальнейшей обработки:
public async Task<Stream> GetObjectStreamAsync(string bucketName, string key)
{
var getRequest = new GetObjectRequest
{
BucketName = bucketName,
Key = key
};
var response = await s3Client.GetObjectAsync(getRequest);
return response.ResponseStream;
}