# Kanject.FileServer

Secure, scalable file storage — declarative resource servers, source-generated upload methods and signed upload URLs, S3-backed, deployed into your own AWS.

> **Note:** Developer guide. For the feature tour, see the [FileServer product page](https://www.kanject.com/baas/fileserver/).

**You'll learn**

- Provision FileServer into your AWS account
- Register it with `AddAwsFileServer`
- Declare a resource server — location, accepted types, size and count limits
- Get source-generated upload methods + signed upload URLs, overriding only for hooks

## Provision

```bash
kanject baas deploy fileserver --env dev
```

## Register it in your service

```csharp
using Kanject.FileServer.Provider.AwsV2.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Register with a typed options delegate. DbConfig carries the AWS region
// and per-stage namespace; lifecycle expiration is opt-in.
builder.Services.AddAwsFileServer(options =>
{
    options.DbConfig.AwsRegion = appSettings.AwsRegion;
    options.DbConfig.Namespace = appSettings.Stage;
});

var app = builder.Build();
app.Run();
```

## Declare a resource server

A resource server is a `partial` class described by attributes: where it stores (`Public`/`Private`), what it accepts, and its limits. Upload and signed-URL methods are **source-generated** — override one only when you need a hook (hashing, transcoding, custom metadata).

```csharp
using Kanject.FileServer.Abstractions.Attributes;
using Kanject.FileServer.Abstractions.Enums;

// Each resource = a declarative server. Public bucket, image-only,
// max 4 MB × 10 files; upload + signed URLs are source-generated.
[FileServer(Version = 2)]
[ResourceServer(Location = StorageLocation.Public, Path = "item-images")]
[AcceptedFileTypes(".jpeg", ".jpg", ".png", ".webp")]
[FileUploadSettings(MaximumFileSize = 4000, MaximumFileCount = 10)]
public partial class ItemResourceServer
{
    // Override the generated method only when you need a hook — here:
    // hash the bytes and transcode to WebP before storage.
    public override async Task<ResourceMetadata?> UploadItemAsync(
        IFormFile file, string resourceId, Guid ownerId,
        Dictionary<string, string>? metadata = null)
    {
        metadata ??= new();
        metadata["contentHash"] = Sha256(file.OpenReadStream());
        return await base.UploadItemAsync(
            await file.ConvertToWebPFile(), resourceId, ownerId, metadata);
    }
}

// Private bucket, PDF-only, 200 KB cap. Zero override required.
[FileServer(Version = 2)]
[ResourceServer(Location = StorageLocation.Private, Path = "shipping-labels")]
[AcceptedFileTypes(".pdf")]
[FileUploadSettings(MaximumFileSize = 200)]
public partial class ShippingLabelResourceServer;
```

## What you get

- **Declarative resource servers** — storage location, accepted types, and size/count limits as attributes.
- **Source-generated upload** — typed `Upload{Resource}Async` methods and pre-signed **upload** URLs, no boilerplate.
- **Content validation** — a shipped `IFileContentValidator` rejects dangerous PDFs (JavaScript / launch actions) and strips JPEG EXIF; plug in your own for more.
- **Public / private + owner scoping** — `StorageLocation.Public`/`Private`, with owner-id validation on read and delete.
- **Accepted-type + size enforcement** — `[AcceptedFileTypes]` and `[FileUploadSettings]` gate every upload.
- **Lifecycle expiration** — opt-in object expiry and incomplete-multipart cleanup.

> **Pitfall:** `MaximumFileSize` is in **kilobytes**. A 4 MB image cap is `4000`, not `4`; a 200 KB cap is `200`. Get the unit wrong and uploads reject far below — or far above — what you intended.

**Recap**

- Provision with `kanject baas deploy fileserver`, register with `AddAwsFileServer(options => …)`.
- A resource server is a declarative `partial` class — location, accepted types, and limits as attributes.
- Upload + signed URLs are source-generated; override a method only to add a hook.
- `MaximumFileSize` is in KB — `4000` for ~4 MB.

## Related modules

- **[Forms](https://www.kanject.com/docs/baas-forms/)** — Form-attachment storage backend.
- **[Identity](https://www.kanject.com/docs/baas-identity/)** — Pair with auth for owner-scoped access.
- **[EventHub](https://www.kanject.com/docs/baas-eventhub/)** — Trigger pipelines on upload.

> **Next step:** Storing user-generated content? Pair FileServer with [Identity](https://www.kanject.com/docs/baas-identity/) for owner-scoped access, or read the [BaaS deployment guide](https://www.kanject.com/docs/baas/).

---
_Source: https://www.kanject.com/docs/baas-fileserver/ · Kanject Docs_
