Synergy.FileStorage 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Synergy.FileStorage --version 1.0.0
                    
NuGet\Install-Package Synergy.FileStorage -Version 1.0.0
                    
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="Synergy.FileStorage" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Synergy.FileStorage" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Synergy.FileStorage" />
                    
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 Synergy.FileStorage --version 1.0.0
                    
#r "nuget: Synergy.FileStorage, 1.0.0"
                    
#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 Synergy.FileStorage@1.0.0
                    
#: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=Synergy.FileStorage&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Synergy.FileStorage&version=1.0.0
                    
Install as a Cake Tool

Synergy.FileStorage

A robust file storage service library for Synergy applications, providing seamless integration with MinIO for object storage and Marten for metadata management.

Features

  • 📁 File Upload: Upload files via Stream or IFormFile with automatic bucket creation
  • 📥 File Download: Download files with or without metadata (content type, filename)
  • 🗑️ File Management: Delete files and check file existence
  • 📊 Metadata Storage: Store file metadata using Marten document database
  • 🔄 Async Operations: All operations are fully asynchronous
  • 🪣 Auto Bucket Creation: Automatically creates MinIO buckets if they don't exist
  • 🏷️ Rich Metadata: Stores file name, content type, uploader information, and more

Installation

Install the package via NuGet:

dotnet add package Synergy.FileStorage

Or via Package Manager:

Install-Package Synergy.FileStorage

Prerequisites

  • .NET 8.0 or later
  • MinIO server (or compatible S3-compatible storage)
  • PostgreSQL database (for Marten metadata storage)

Dependencies

  • Minio (7.0.0) - S3-compatible object storage client
  • Marten (8.17.0) - Document database for PostgreSQL
  • MediatR (12.2.0) - Mediator pattern implementation
  • MassTransit.AspNetCore (7.3.1) - Message bus integration

Quick Start

1. Configure MinIO Client

using Minio;

var minioClient = new MinioClient()
    .WithEndpoint("localhost:9000")
    .WithCredentials("minioadmin", "minioadmin")
    .Build();

2. Register Services

using Synergy.FileStorage.Services;

// Register MinIO client
services.AddSingleton<IMinioClient>(minioClient);

// Register FileStorageService
services.AddScoped<IFileStorageService>(provider =>
{
    var minioClient = provider.GetRequiredService<IMinioClient>();
    return new FileStorageService(minioClient, "my-bucket-name");
});

3. Use the Service

using Synergy.FileStorage.Services;

public class MyController : ControllerBase
{
    private readonly IFileStorageService _fileStorageService;

    public MyController(IFileStorageService fileStorageService)
    {
        _fileStorageService = fileStorageService;
    }

    [HttpPost("upload")]
    public async Task<IActionResult> UploadFile(IFormFile file)
    {
        var fileId = await _fileStorageService.UploadFormFileAsync(
            file, 
            file.FileName, 
            file.ContentType, 
            file.Length, 
            Guid.Parse("user-id-here")
        );
        
        return Ok(new { FileId = fileId });
    }

    [HttpGet("download/{fileId}")]
    public async Task<IActionResult> DownloadFile(Guid fileId)
    {
        var (stream, contentType, fileName) = await _fileStorageService
            .DownloadFileWithMetadataAsync(fileId);
        
        return File(stream, contentType, fileName);
    }
}

API Reference

IFileStorageService

UploadFileAsync

Uploads a file from a Stream.

Task<Guid> UploadFileAsync(
    Stream fileStream, 
    string fileName, 
    string contentType, 
    long contentLength,
    Guid uploadedBy, 
    CancellationToken cancellationToken = default
)

Returns: The unique identifier (Guid) of the uploaded file.

UploadFormFileAsync

Uploads a file from an IFormFile (ASP.NET Core).

Task<Guid> UploadFormFileAsync(
    IFormFile formFile, 
    string fileName, 
    string contentType, 
    long contentLength,
    Guid uploadedBy, 
    CancellationToken cancellationToken = default
)

Returns: The unique identifier (Guid) of the uploaded file.

DownloadFileAsync

Downloads a file as a Stream.

Task<Stream> DownloadFileAsync(
    Guid fileId, 
    CancellationToken cancellationToken = default
)

Returns: A Stream containing the file data.

DownloadFileWithMetadataAsync

Downloads a file with its metadata (content type and filename).

Task<(Stream Stream, string ContentType, string? FileName)> DownloadFileWithMetadataAsync(
    Guid fileId, 
    CancellationToken cancellationToken = default
)

Returns: A tuple containing the file stream, content type, and filename.

DeleteFileAsync

Deletes a file from storage.

Task DeleteFileAsync(
    string objectName, 
    CancellationToken cancellationToken = default
)
FileExistsAsync

Checks if a file exists in storage.

Task<bool> FileExistsAsync(
    string objectName, 
    CancellationToken cancellationToken = default
)

Returns: true if the file exists, false otherwise.

IFileRepository

Repository interface for managing file metadata using Marten.

Task<File?> GetByIdAsync(Guid fileId, CancellationToken cancellationToken = default);
Task SaveAsync(File file, CancellationToken cancellationToken = default);
Task<IEnumerable<File>> GetAllAsync(CancellationToken cancellationToken = default);

File Model

public record File
{
    public Guid Id { get; init; }
    public string FileName { get; init; }
    public string ContentType { get; init; }
    public long FileSize { get; init; }
    public DateTime UploadedAt { get; init; }
    public bool IsDeleted { get; init; }
}

Configuration

MinIO Configuration

Ensure your MinIO server is running and accessible. The service will automatically create the specified bucket if it doesn't exist.

Bucket Name

The bucket name is provided during service registration. Choose a meaningful name for your application:

new FileStorageService(minioClient, "my-application-files")

Best Practices

  1. Error Handling: Always wrap file operations in try-catch blocks
  2. Stream Disposal: Ensure streams are properly disposed after use
  3. Bucket Naming: Use descriptive bucket names that match your application's purpose
  4. User Tracking: Always provide valid user IDs when uploading files for audit purposes
  5. Content Type: Always specify the correct content type for proper file handling

Example: Complete File Upload/Download Flow

public class FileController : ControllerBase
{
    private readonly IFileStorageService _fileStorageService;
    private readonly IFileRepository _fileRepository;

    public FileController(
        IFileStorageService fileStorageService,
        IFileRepository fileRepository)
    {
        _fileStorageService = fileStorageService;
        _fileRepository = fileRepository;
    }

    [HttpPost("upload")]
    public async Task<IActionResult> Upload(IFormFile file, Guid userId)
    {
        try
        {
            // Upload to MinIO
            var fileId = await _fileStorageService.UploadFormFileAsync(
                file, file.FileName, file.ContentType, file.Length, userId);

            // Save metadata to database
            var fileRecord = new Synergy.FileStorage.DTOs.File
            {
                Id = fileId,
                FileName = file.FileName,
                ContentType = file.ContentType,
                FileSize = file.Length,
                UploadedAt = DateTime.UtcNow,
                IsDeleted = false
            };
            
            await _fileRepository.SaveAsync(fileRecord);

            return Ok(new { FileId = fileId });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }

    [HttpGet("{fileId}")]
    public async Task<IActionResult> Download(Guid fileId)
    {
        try
        {
            // Get metadata
            var fileRecord = await _fileRepository.GetByIdAsync(fileId);
            if (fileRecord == null || fileRecord.IsDeleted)
                return NotFound();

            // Download file
            var (stream, contentType, fileName) = await _fileStorageService
                .DownloadFileWithMetadataAsync(fileId);

            return File(stream, contentType, fileName ?? fileRecord.FileName);
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }
}

License

This project is licensed under the MIT License.

Contributing

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

Support

For issues, questions, or contributions, please visit:

Version History

  • 1.0.0 - Initial release with file upload, download, and management capabilities
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.1.0 204 1/17/2026
1.0.0 160 1/9/2026