Canducci.FileUpload.Database 1.0.0.5

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

Canducci.FileUpload Ecosystem

A comprehensive file upload solution for ASP.NET Core with validation, flexible configuration, and database persistence.

NuGet NuGet Database NuGet Downloads GitHub License: MIT .NET

Portuguese: README_PTBR.md

Overview

The Canducci.FileUpload ecosystem consists of two core packages that work together:

Package Version Description
Canducci.FileUpload 1.0.0.5 Core file upload with validation, async/sync operations, and multiple filename strategies
Canducci.FileUpload.Database 1.0.0.5 Database persistence layer with automatic table creation at runtime (IHostedService)

Both packages support .NET 8, 9, and 10.


Quick Start

1. Install Packages

# Core file upload
dotnet add package Canducci.FileUpload

# Database persistence (optional)
dotnet add package Canducci.FileUpload.Database

2. Configure Services (Program.cs)

using Canducci.FileUpload.Extensions;
using Canducci.FileUpload.Database.Extensions;
using SqlKata.Compilers;
using System.Data.SqlClient;
using MySql.Data.MySqlClient;
using Npgsql;
using Microsoft.Data.Sqlite;
using FirebirdSql.Data.FirebirdClient;
using Oracle.ManagedDataAccess.Client;

var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;

// Core file upload
builder.Services.AddFileUpload(config =>
{
    config.FileUploadConfigurationName = FileUploadConfigurationName.Guid;
});

// Database persistence - Choose ONE provider:

// SQL Server
builder.Services.AddFileUploadTable<long, long>(
    connectionFactory: _ => new SqlConnection(configuration.GetConnectionString("SQLServer")),
    compiler: new SqlServerCompiler(),
    tableFields: TableFields.CreateSqlServer()
);

// PostgreSQL
builder.Services.AddFileUploadTable<long, long>(
    connectionFactory: _ => new NpgsqlConnection(configuration.GetConnectionString("Postgres")),
    compiler: new PostgresCompiler(),
    tableFields: TableFields.CreatePostgres()
);

// SQLite
builder.Services.AddFileUploadTable<long, long>(
    connectionFactory: _ => new SqliteConnection(configuration.GetConnectionString("SqLite")),
    compiler: new SqliteCompiler(),
    tableFields: TableFields.CreateSQLite()
);

// MySQL
builder.Services.AddFileUploadTable<long, long>(
    connectionFactory: _ => new MySqlConnection(configuration.GetConnectionString("MySQL")),
    compiler: new MySqlCompiler(),
    tableFields: TableFields.CreateMySQL()
);

// Firebird
builder.Services.AddFileUploadTable<long, long>(
    connectionFactory: _ => new FbConnection(configuration.GetConnectionString("Firebird")),
    compiler: new FirebirdCompiler(),
    tableFields: TableFields.CreateFirebird()
);

// Oracle
builder.Services.AddFileUploadTable<long, long>(
    connectionFactory: _ => new OracleConnection(configuration.GetConnectionString("Oracle")),
    compiler: new OracleCompiler(),
    tableFields: TableFields.CreateOracle()
);

var app = builder.Build();

3. Use in Controller

using Canducci.FileUpload;
using Canducci.FileUpload.Database;
using Canducci.FileUpload.Enuns;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class FilesController : ControllerBase
{
    [HttpPost("upload")]
    public async Task<IActionResult> Upload(
        IFileUpload fileUpload,
        ITableFileUploadService<long, long> tableService,
        CancellationToken cancellationToken)
    {
        var options = new FileUploadOptions(
            maxFileSizeBytes: 10 * 1024 * 1024,
            rejectEmptyFiles: true,
            allowedExtensions: ".jpg", ".jpeg", ".png", ".pdf", ".docx");

        var result = await fileUpload.SaveAsync("uploads", options, cancellationToken);

        // Persist to database
        if (result.Status == FileUploadStatus.AllSucceeded ||
            result.Status == FileUploadStatus.PartialSuccess)
        {
            await tableService.ExecuteAsync(fileUpload, "uploads", options, 1, 1);
        }

        return result.Status switch
        {
            FileUploadStatus.AllSucceeded => Ok(new {
                Message = "All files saved",
                Count = result.SuccessCount,
                Files = result.Files.Select(f => new { f.FileNameSave, f.Path })
            }),
            FileUploadStatus.PartialSuccess => Ok(new {
                Message = "Some files saved",
                Succeeded = result.SuccessCount,
                Failed = result.FailureCount
            }),
            FileUploadStatus.AllFailed => BadRequest(new {
                Message = "All files failed",
                Errors = result.Files.Select(f => f.Exception?.Message)
            }),
            _ => BadRequest(new { Error = "No files provided" })
        };
    }
}

Canducci.FileUpload (Core)

Features

  • Validation: File size, extension allowlist, empty file rejection
  • Filename Strategies: Random, GUID, GUID v7, ULID
  • Async/Sync: Full CancellationToken support
  • Multi-file: Single or batch upload handling
  • Security: Path sanitization, atomic saves, overwrite prevention

Configuration

builder.Services.AddFileUpload(config =>
{
    config.FileUploadConfigurationName = FileUploadConfigurationName.Guid;
    // Available: Random, Guid, GuidVersion7, Ulid (>= 1.0.0.4)
});

FileUploadOptions

// Defaults: 10MB, reject empty, no extension restrictions
var options = new FileUploadOptions();

// Parameterized constructors
var options = new FileUploadOptions(5_000_000, false); // size, rejectEmpty
var options = new FileUploadOptions(2_000_000, true, ".pdf", ".docx", ".xlsx");

// Fluent API for common extension groups
options.AllowedExtensions
    .AddImages()      // 10 image extensions
    .AddDocuments()   // 10 document extensions
    .AddArchives();   // 5 archive extensions

Result Handling

var result = fileUpload.Save("uploads", options);

switch (result.Status)
{
    case FileUploadStatus.AllSucceeded:
        // All files saved
        break;
    case FileUploadStatus.PartialSuccess:
        // result.SuccessCount succeeded, result.FailureCount failed
        break;
    case FileUploadStatus.AllFailed:
        // All failed
        break;
    case FileUploadStatus.Empty:
        // No files provided
        break;
}

Canducci.FileUpload.Database

Features

  • Automatic Table Creation: IHostedService creates table at application startup
  • Multi-database: MySQL, SQL Server, Oracle, SQLite, Firebird, PostgreSQL
  • Multi-tenant/User: Generic TTenant, TUser types
  • CRUD Operations: Add, Update, Get by ID, List with filters
  • SqlKata Powered: Type-safe query building

Supported Databases

// SQL Server
new SqlServerCompiler()

// MySQL
new MySqlCompiler()

// PostgreSQL
new PostgresCompiler()

// SQLite
new SqliteCompiler()

// Oracle
new OracleCompiler()

// Firebird
new FirebirdCompiler()

TableFields - Column Mapping

// Default (snake_case)
var fields = TableFields.Default;

// SQL Server (PascalCase)
var fields = TableFields.CreateSqlServer();

// MySQL (snake_case)
var fields = TableFields.CreateMySQL();

// PostgreSQL (UPPER_CASE)
var fields = TableFields.CreatePostgres();

// Custom
var fields = TableFields.Create(
    table: "uploads",
    id: "id",
    tenantReference: "tenant_id",
    userReference: "user_id",
    extension: "ext",
    fileName: "original_name",
    path: "file_path",
    length: "size_bytes",
    createdAt: "created_at",
    updateAt: "updated_at"
);

Services

Interface Description
ITableService<TTenant, TUser> Low-level CRUD operations
ITableFileUploadService<TTenant, TUser> High-level upload + persistence coordination

Usage Patterns

1. Automatic Upload + Persist
[HttpPost]
public async Task<IActionResult> Upload(
    IFileUpload fileUpload,
    ITableFileUploadService<long, long> tableService,
    CancellationToken ct)
{
    var options = new FileUploadOptions(10_000_000, true, ".pdf", ".docx");

    // Upload to disk AND persist to database in one call
    var success = await tableService.ExecuteAsync(fileUpload, "uploads", options,
                                                  tenantId: 1, userId: 100);

    return success ? Ok() : BadRequest();
}
2. Manual Persistence
var result = await fileUpload.SaveAsync("uploads", options, ct);

if (result.Status != FileUploadStatus.Empty)
{
    // Persist successful files
    var records = tableService.Add(result, tenantId: 1, userId: 100);
}
3. Query Records
// All records
var all = tableService.ToList();

// By tenant
var tenantFiles = tableService.ToListByTenant(tenantId: 1);

// By user
var userFiles = tableService.ToListByUser(userId: 100);

// By ID
var file = tableService.FirstOrDefault(id: 42);

Version History

Version Date Changes
1.0.0.0 Initial Core file upload
1.0.0.1 FileUploadStatus enum, SuccessCount/FailureCount
1.0.0.2 XML docs, Data Annotations support
1.0.0.3 Multiple constructors, Fluent API
1.0.0.4 GUID v7, ULID filename strategies
1.0.0.5 Database integration (TableService, TableFileUploadService, IHostedService)

Current Stable: 1.0.0.5


Example Projects

Project Description
WebAppTest Full Razor Views + Controllers demo
WebFileUploadBasic Minimal basic upload
WebFilesUploadBasic Multiple files handling
WebFilesUploadBasicGuidNameGenerate GUID filename strategy
WebFilesUploadBasicOnlyImages Image-only uploads
WebFilesUploadBasicOnlyImagensDataAnnotation Data Annotations validation
Canducci.FileUpload.FluentValidation FluentValidation integration

Security

  • ✅ Filename sanitization & path traversal protection
  • ✅ Case-insensitive extension validation
  • ✅ Overwrite prevention (unique filenames)
  • ✅ Atomic saves (temp file → rename)
  • ✅ CancellationToken support
  • ✅ Granular per-file error handling

Requirements

  • .NET 8.0 or later
  • ASP.NET Core

License

MIT License


Author

Fulvio Canducci - GitHub

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 is compatible.  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 is compatible.  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.0.7 80 10/20/2026
1.0.0.5 82 10/13/2026

Initial release of Database integration for Canducci.FileUpload.Database