BarakoCMS.Files
4.5.0
See the version list below for details.
dotnet add package BarakoCMS.Files --version 4.5.0
NuGet\Install-Package BarakoCMS.Files -Version 4.5.0
<PackageReference Include="BarakoCMS.Files" Version="4.5.0" />
<PackageVersion Include="BarakoCMS.Files" Version="4.5.0" />
<PackageReference Include="BarakoCMS.Files" />
paket add BarakoCMS.Files --version 4.5.0
#r "nuget: BarakoCMS.Files, 4.5.0"
#:package BarakoCMS.Files@4.5.0
#addin nuget:?package=BarakoCMS.Files&version=4.5.0
#tool nuget:?package=BarakoCMS.Files&version=4.5.0
<div align="center"> <h1>BarakoCMS.Files</h1> <p><em>Optional file-attachment module for barakoCMS.</em></p> </div>
Adds file upload + download to barakoCMS, storing bytes in Postgres via Marten. Handy for receipts, photos, and documents attached to your own records.
Enable it
dotnet add package BarakoCMS.Files
builder.Services.AddBarakoCMS(builder.Configuration);
var app = builder.Build();
app.UseBarakoCMS();
The package reference plus a restart is the install. AddBarakoCMS finds every module in the
application's dependency context, and BarakoCMS:Modules:Enabled decides which of them run
(BarakoCMS__Modules__Enabled=Files). Unset, every referenced module runs and the API logs
one warning saying so. To name it by hand instead, put
modules.Add(new BarakoCMS.Files.FilesModule())
in the AddBarakoCMS callback; discovery skips a type the host already added. See MODULES.md in
the repository.
Endpoints
| Method & path | Purpose |
|---|---|
POST /api/files |
Upload one PNG, JPEG, GIF, WebP, AVIF or PDF (up to 10 MB, multipart). The part's Content-Type must be exactly one of those, and the file must start the way that format does. Returns { id, fileName, contentType, size }. |
GET /api/files/{id} |
Stream the file back with its original content type. Requires a Bearer token. |
GET /api/files |
List uploads, newest first, paginated. ?q= matches a substring of the name, ?contentType=image/ a type or prefix. |
GET /api/files/{id}/meta |
The record without the bytes: name, type, size, public flag, alt text, caption. |
PATCH /api/files/{id} |
Set alt and caption. A field left out is unchanged; an empty string clears it. |
GET /api/files/{id}/usage |
The entries whose data references the file, by id or by URL. Paginated. |
DELETE /api/files/{id} |
Remove the file, its cached resizes and their bytes. 409 with the first ten usages while an entry references it; ?force=true deletes anyway. |
GET /api/public/files/{id} |
Anonymous download of a public file. Private files are 404. |
GET /api/public/files/{id}/meta |
Anonymous alt text and caption for a public file. Private files are 404. |
Attach the returned id to your own documents; fetch it later with the download endpoint. Because
GET /api/files/{id} requires authentication, browser <img>/<a> tags cannot load it directly:
fetch it with the token and use an object URL, or upload with isPublic=true and use the public
route.
Every route except the download and the two public ones is gated on the upload_files capability.
The download asks only for a signed-in user, and then for the file to be theirs. A private file
somebody else uploaded is downloaded, and deleted, only by a caller holding manage_all_files;
upload_files alone does not open it. The module grants both capabilities to the seeded Admin
role at startup, SuperAdmin satisfies both, and any role you create can be given either. The
where-used lookup scans the tenant's entries for the file's id or
its storage key as a substring of any field, so it finds the id a file field holds, a bare id in any other field, a /api/public/files/{id} URL
with or without ?w=, and an object store's public URL. A usage row always carries the entry's id
and status; its title is there only when the caller holds read on the type and the sensitivity
scrub leaves it, the same two checks as GET /api/contents.
Using files from another module
The module implements IFileStore from BarakoCMS.Abstractions, so the core and other modules can
store, read and delete a file without referencing this package. Every call works in the scope's
tenant.
public sealed class Receipts(IFileStore files)
{
public async Task<Guid?> KeepAsync(Stream pdf, Guid payer, CancellationToken ct)
{
var saved = await files.SaveAsync(
new FileToStore { Content = pdf, FileName = "receipt.pdf", ContentType = "application/pdf", Owner = payer }, ct);
return saved.File?.Id; // null: saved.Refused says why
}
public Task<Stream?> ReadAsync(Guid id, ClaimsPrincipal user, CancellationToken ct) =>
files.OpenAsync(id, user, ct);
}
FindPublicAsync,OpenPublicAsyncandPublicUrlAsynctake no caller and answer for public files only, the same filesGET /api/public/files/{id}serves. A private file reads as absent. The workflowEmailaction uses these for attachments; seedocs/configuring-email.md.PublicUrlAsyncgives the object store's URL when the store serves the file itself, and otherwise the path/api/public/files/{id}.FindAsyncandOpenAsynctake the signed-in user and hand over what that user could download: a public file, or a private one that is theirs or thatmanage_all_filesopens for them, the ruleGET /api/files/{id}applies. An API key, a principal that is not signed in and a token for another tenant read public files only. Pass the current request's principal: token revocation, tenant activity and device trust are the request pipeline's checks and are not run again here.SaveAsyncruns the checksPOST /api/filesruns (type, content, 10 MB, the scanner when configured) and writes the record an upload writes, owned byOwner, so the routes above serve it as they serve an upload. A refused file is not stored, and a scanner refusal is written to the audit log. It does not checkupload_files: the calling module decides who may reach it. The file is held in memory once while it is checked and stored (its own size from a seekable stream, up to twice that from one that is not), and the Postgres storage copies it twice more.DeleteAsyncdeletes for a callerDELETE /api/files/{id}would delete for, and answersInUsewhile an entry names the file unless forced.FindPublicManyAsyncandFindManyAsyncanswer the two finds for many ids in one query. Each answer carries the file'sPublicUrl(null when it is private),AltandCaption. The core's file fields resolve through these; seedocs/file-fields.md.
SaveAsync and DeleteAsync commit, through the scope's session. Call them before staging
anything else on it: they throw InvalidOperationException when work is already staged, so a
refused save never commits a caller's rows. Inside a content batch nothing commits until the batch
does, and with an object store the bytes do not roll back with it; MODULES.md says what that
leaves behind.
There is no member that reads or deletes a private file for no user. A job that runs without one
can store a file and read public files. A file stored with no Owner shows the empty id as
uploadedBy on GET /api/files and GET /api/files/{id}/meta.
Notes
Files live in the stored_files Marten document (bytes in Postgres). This suits low-to-moderate
volumes of small files; for large-scale blob storage, use an object store instead.
Requires
barakoCMS and BarakoCMS.Abstractions, at the versions NuGet lists as this package's dependencies. Neither is older than 4.3.0, the release that added BarakoCMS.Abstractions. Targets .NET 10.
License
MPL-2.0 © BaryoDev
If barakoCMS is useful to you, a star on the repository helps other people find it.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- AspNetCore.HealthChecks.Npgsql (>= 9.0.0)
- AspNetCore.HealthChecks.System (>= 9.0.0)
- AspNetCore.HealthChecks.UI (>= 9.0.0)
- AspNetCore.HealthChecks.UI.Client (>= 9.0.0)
- AspNetCore.HealthChecks.UI.InMemory.Storage (>= 9.0.0)
- BarakoCMS (>= 4.7.0)
- BarakoCMS.Abstractions (>= 4.7.0)
- BCrypt.Net-Next (>= 4.2.0)
- Carom (>= 2.0.1)
- Carom.Extensions (>= 2.0.1)
- FastEndpoints (>= 8.3.0)
- FastEndpoints.Security (>= 8.3.0)
- FastEndpoints.Swagger (>= 8.3.0)
- IdentityModel (>= 7.0.0)
- JasperFx (>= 2.75.2)
- KubernetesClient (>= 18.0.13)
- Marten (>= 9.40.0)
- Microsoft.Extensions.DependencyModel (>= 10.0.12)
- Microsoft.IdentityModel.JsonWebTokens (>= 8.23.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.19.1)
- OpenTelemetry.Extensions.Hosting (>= 1.19.1)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.19.0)
- OpenTelemetry.Instrumentation.Http (>= 1.19.0)
- Otp.NET (>= 1.4.1)
- prometheus-net.AspNetCore (>= 8.2.1)
- Serilog.AspNetCore (>= 10.0.0)
- Serilog.Sinks.Console (>= 6.1.1)
- Serilog.Sinks.File (>= 7.0.0)
- SkiaSharp (>= 4.153.1)
- SkiaSharp.NativeAssets.Linux.NoDependencies (>= 4.153.1)
- System.IdentityModel.Tokens.Jwt (>= 8.23.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on BarakoCMS.Files:
| Package | Downloads |
|---|---|
|
BarakoCMS.Files.S3
S3-compatible object storage provider for the barakoCMS Files module. Works with AWS S3, Cloudflare R2, and self-hosted S3-compatible stores such as SeaweedFS. Public files get a direct, CDN-friendly URL; private files are proxied through the API. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.1.0 | 41 | 10/23/2026 |
| 5.0.0 | 95 | 10/14/2026 |
| 4.6.0 | 104 | 10/12/2026 |
| 4.5.0 | 88 | 10/11/2026 |
| 4.4.0 | 107 | 10/4/2026 |
| 4.3.1 | 104 | 9/29/2026 |
| 4.3.0 | 120 | 9/21/2026 |
| 4.2.1 | 106 | 9/18/2026 |
| 4.1.1 | 119 | 9/18/2026 |
| 4.0.0 | 123 | 9/7/2026 |
| 0.2.0 | 141 | 8/20/2026 |
| 0.1.3 | 146 | 8/15/2026 |
| 0.1.2 | 222 | 8/3/2026 |
| 0.1.1 | 160 | 7/21/2026 |
| 0.1.0 | 115 | 7/15/2026 |