# Kanject.Core.FileRepository

An S3 wrapper that treats object storage as a typed store with stream-friendly uploads, presigned upload/download links, and private/public storage locations. Register one repository, inject `IFileRepository`, and skip the raw AWS SDK ceremony.

## Install

```bash
dotnet add package Kanject.Core.FileRepository.Provider.AwsS3
```

The AWS S3 provider package pulls in `Kanject.Core.FileRepository.Abstractions` (which defines `IFileRepository`) transitively.

## Register

```csharp
using Kanject.Core.FileRepository.Provider.AwsS3.Abstractions.Extensions;

builder.Services.AddAwsS3FileRepository(options =>
{
    options.BucketName = appSettings.UploadsBucket;
    options.Region     = appSettings.AwsRegion;

    // Credentials resolve from configuration — in a deployed Kanject
    // service these come from Parameter Store / Secrets Manager at deploy.
    options.AWSAccessKey = appSettings.AwsAccessKey;
    options.AWSSecretKey = appSettings.AwsSecretKey;
});
```

`AddAwsS3FileRepository` registers `IFileRepository` as a singleton. Keyed overloads — `AddAwsS3FileRepository("thumbnails", …)` — let one service talk to several buckets, resolved with `[FromKeyedServices]`.

## Use it

```csharp
public class AvatarService(IFileRepository files)
{
    // Upload a stream. Returns the stored file name, its URL, and — for a
    // private object served via a signed link — the URL's expiry.
    public async Task<string> UploadAsync(Guid userId, Stream content, string contentType)
    {
        UploadFileResponse result = await files.UploadFileAsync(
            content,
            name: "avatar",
            path: $"users/{userId}",
            contentType: contentType,
            storageLocation: StorageLocationEnum.Public);

        return result.FileUrl;
    }

    // A time-limited download link for a private object. Expiry is a per-call
    // DateTime, not a global setting; fileAccess scopes what the link permits.
    public string SignedInvoiceLink(string invoiceName)
    {
        (string fileName, string link) = files.GenerateFileLink(
            DateTime.UtcNow.AddHours(1),
            name: invoiceName,
            storageLocation: StorageLocationEnum.Private,
            fileAccess: FileAccessTypeEnum.Read);

        return link;
    }
}
```

## What ships with it

- `UploadFileAsync(Stream …)` and an `IFormFile` overload → `UploadFileResponse { FileName, FileUrl, FileUrlExpiryDate }`
- `GetFileAsync` (→ `Stream`), `GetFileAsByteArrayAsync` (→ `byte[]`), and `GetFileWithMetadataAsync`
- `DeleteFileAsync`, `FileExistsAsync`, and `GetFileMetadataAsync`
- `GenerateFileLink(...)` / `GenerateUploadFileLink(...)` — presigned download/upload links, expiry passed per call as a `DateTime`
- `StorageLocationEnum` (`Private` / `Public`) selects the storage folder; `FileAccessTypeEnum` (`Read` / `Write` / `Delete`) scopes a signed link
- Bucket lifecycle helpers on the settings — expiration and incomplete-multipart-upload cleanup

> **Pair with:** For a managed file-server experience (CDN, virus scanning, versioning, RBAC), see [Kanject.FileServer](https://www.kanject.com/baas/fileserver) — it builds on this library and adds the operational layer.

---
_Source: https://www.kanject.com/docs/core-files/ · Kanject Docs_
