Flynk.Net.Services.Storage.Aws.S3 1.0.1

Prefix Reserved
dotnet add package Flynk.Net.Services.Storage.Aws.S3 --version 1.0.1
                    
NuGet\Install-Package Flynk.Net.Services.Storage.Aws.S3 -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Flynk.Net.Services.Storage.Aws.S3" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Flynk.Net.Services.Storage.Aws.S3" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Flynk.Net.Services.Storage.Aws.S3" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Flynk.Net.Services.Storage.Aws.S3 --version 1.0.1
                    
#r "nuget: Flynk.Net.Services.Storage.Aws.S3, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Flynk.Net.Services.Storage.Aws.S3@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Flynk.Net.Services.Storage.Aws.S3&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Flynk.Net.Services.Storage.Aws.S3&version=1.0.1
                    
Install as a Cake Tool

Flynk.Net.Services.Storage.Aws.S3

A reusable AWS S3 file storage service for .NET applications. This NuGet package provides a simple and flexible way to integrate S3 storage capabilities into your projects.

Features

  • Simple File Operations: Upload, download, delete files with ease
  • Presigned URLs: Generate secure temporary URLs for uploads and downloads
  • Batch Operations: Delete multiple files at once
  • Versioning Support: Enable and manage file versions
  • Public Access Control: Set files as public or private
  • CORS Configuration: Configure CORS for browser-based uploads
  • Metadata Management: Attach and update file metadata
  • Content Type Detection: Automatic content type detection based on file extensions
  • Lifecycle Management: Configure automatic file expiration
  • Fluent Configuration: Multiple ways to configure the service

Installation

dotnet add package Flynk.Net.Services.Storage.Aws.S3

Quick Start

1. Configure in appsettings.json

{
  "S3Storage": {
    "AccessKey": "your-access-key",
    "SecretKey": "your-secret-key",
    "BucketName": "your-bucket-name",
    "Region": "us-east-1",
    "PresignedUrlExpirationMinutes": 60,
    "UseServerSideEncryption": true,
    "AllowedCorsOrigins": ["http://localhost:3000", "https://yourdomain.com"]
  }
}

2. Register the service

// In Program.cs or Startup.cs

// Using configuration from appsettings.json
builder.Services.AddS3Storage(builder.Configuration);

// Or using inline configuration
builder.Services.AddS3Storage(options =>
{
    options.AccessKey = "your-access-key";
    options.SecretKey = "your-secret-key";
    options.BucketName = "your-bucket-name";
    options.Region = "us-east-1";
});

// Or using the fluent builder
builder.Services.AddS3StorageBuilder()
    .WithCredentials("access-key", "secret-key")
    .WithBucket("bucket-name")
    .WithRegion("us-east-1")
    .WithServerSideEncryption()
    .WithCorsOrigins("http://localhost:3000", "https://yourdomain.com")
    .Build();

3. Use the service

public class FileController : ControllerBase
{
    private readonly IS3StorageService _s3Storage;

    public FileController(IS3StorageService s3Storage)
    {
        _s3Storage = s3Storage;
    }

    [HttpPost("upload")]
    public async Task<IActionResult> Upload(IFormFile file)
    {
        using var stream = file.OpenReadStream();
        var key = S3KeyGenerator.GenerateKey("org-123", "documents", file.FileName);

        var result = await _s3Storage.UploadAsync(
            stream,
            key,
            file.ContentType,
            new Dictionary<string, string>
            {
                ["original-name"] = file.FileName,
                ["uploaded-by"] = User.Identity.Name
            }
        );

        if (result.Success)
        {
            return Ok(new { key = result.Key, etag = result.ETag });
        }

        return BadRequest(result.ErrorMessage);
    }

    [HttpGet("download/{key}")]
    public async Task<IActionResult> Download(string key)
    {
        var stream = await _s3Storage.DownloadAsync(key);
        var contentType = ContentTypeHelper.GetContentType(key);

        return File(stream, contentType);
    }

    [HttpGet("presigned-url/{key}")]
    public async Task<IActionResult> GetPresignedUrl(string key)
    {
        var url = await _s3Storage.GetPresignedDownloadUrlAsync(key, 60);
        return Ok(new { url });
    }

    [HttpDelete("{key}")]
    public async Task<IActionResult> Delete(string key)
    {
        var success = await _s3Storage.DeleteAsync(key);
        return success ? Ok() : NotFound();
    }
}

Advanced Usage

Versioning

// Enable versioning for the bucket
await _s3Storage.EnableVersioningAsync();

// Get all versions of a file
var versions = await _s3Storage.GetVersionsAsync("path/to/file.pdf");

// Restore a specific version
await _s3Storage.RestoreVersionAsync("path/to/file.pdf", "versionId123");

// Delete a specific version
await _s3Storage.DeleteVersionAsync("path/to/file.pdf", "versionId123");

Public Access

// Make a file publicly accessible
await _s3Storage.SetAccessControlAsync("path/to/file.jpg", isPublic: true);

// Get the public URL
var publicUrl = _s3Storage.GetPublicUrl("path/to/file.jpg");

Batch Operations

// List files with a prefix
var files = await _s3Storage.ListAsync("org-123/documents/", maxKeys: 100);

// Delete multiple files
var keysToDelete = files.Select(f => f.Key);
await _s3Storage.DeleteManyAsync(keysToDelete);

Metadata Management

// Get file metadata
var metadata = await _s3Storage.GetMetadataAsync("path/to/file.doc");

// Update metadata
await _s3Storage.UpdateMetadataAsync("path/to/file.doc", new Dictionary<string, string>
{
    ["status"] = "processed",
    ["processed-date"] = DateTime.UtcNow.ToString()
});

CORS Configuration

// Configure CORS for browser uploads
await _s3Storage.ConfigureCorsAsync(new List<string>
{
    "https://app.example.com",
    "https://www.example.com"
});

Lifecycle Management

// Auto-delete files after 30 days
await _s3Storage.ConfigureLifecycleAsync(expirationDays: 30);

Utility Classes

S3KeyGenerator

Helper class for generating consistent S3 keys:

// Generate a unique key for a file
var key = S3KeyGenerator.GenerateKey("org-123", "media", "photo.jpg");
// Result: "org-123/media/[guid].jpg"

// Generate a thumbnail key
var thumbKey = S3KeyGenerator.GenerateThumbnailKey(originalKey, "200x200");

// Extract parts from a key
var orgId = S3KeyGenerator.GetOrganizationId(key);
var folder = S3KeyGenerator.GetFolder(key);
var fileName = S3KeyGenerator.GetFileName(key);

ContentTypeHelper

Helper class for managing content types:

// Get content type from file name
var contentType = ContentTypeHelper.GetContentType("document.pdf");
// Result: "application/pdf"

// Check file type
bool isImage = ContentTypeHelper.IsImage(contentType);
bool isVideo = ContentTypeHelper.IsVideo(contentType);
bool isDocument = ContentTypeHelper.IsDocument(contentType);

Configuration Options

Option Description Default
AccessKey AWS Access Key ID Required
SecretKey AWS Secret Access Key Required
BucketName S3 Bucket name Required
Region AWS Region us-east-1
PresignedUrlExpirationMinutes Default expiration for presigned URLs 60
UseServerSideEncryption Enable AES256 server-side encryption true
AllowedCorsOrigins List of allowed CORS origins null

Requirements

  • .NET 9.0 or higher
  • AWS S3 bucket with appropriate permissions
  • AWS credentials with S3 access

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues and questions, please open an issue on the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 902 10/28/2025
1.0.0 224 10/28/2025