Skip to content
File System

File System

Overview

The fsys package provides a unified file storage abstraction with multiple provider backends. The api/fs package integrates this into the framework with multi-disk management.

Architecture

Application Code
      |
      v
+------------------+
|  fs.FileSystem   |  <-- Multi-disk manager (api/fs)
+------------------+
      |
      v
+------------------+
|  fsys.FS         |  <-- Unified interface
+------------------+
      |
      +-- LocalStorage   (local filesystem)
      +-- S3Storage      (Amazon S3)
      +-- GCSStorage     (Google Cloud Storage)
      +-- MemoryStorage  (in-memory, for testing)

FS Interface

All providers implement a common interface:

type FS interface {
    Driver() string
    Read(path string) (io.ReadCloser, error)
    Write(path string, contents []byte) error
    Delete(path string) error
    Exists(path string) (bool, error)
    Rename(oldPath, newPath string) error
    Copy(sourcePath, destinationPath string) error
    CreateDirectory(path string) error
    GetUrl(path string) (string, error)
    Open(path string) (*os.File, error)
    Upload(file multipart.File, header *multipart.FileHeader, dir string) (*os.File, error)
}

Framework Integration

Provider

The filesystem is registered via the fs.Provider in bootstrap/providers.go:

func LoadProviders() []app.Provider {
    return []app.Provider{
        &fs.Provider{},
    }
}

Access

filesys := app.Get[*fs.FileSystem](a)

// Get a specific disk
disk, err := filesys.Disk("s3")
disk, err := filesys.Disk() // Returns default disk (from FILESYSTEM_DISK env)

Usage

disk, _ := filesys.Disk("local")

// Write
disk.Write("uploads/report.pdf", data)

// Read
reader, _ := disk.Read("uploads/report.pdf")
defer reader.Close()

// Check existence
exists, _ := disk.Exists("uploads/report.pdf")

// Delete
disk.Delete("uploads/report.pdf")

// Get URL
url, _ := disk.GetUrl("uploads/report.pdf")

// Upload from request
disk.Upload(file, header, "avatars")

Configuration

Configuration is set in internal/configs/filesystems.go:

config.Set("filesystems", config.M{
    "default": config.MustEnv("FILESYSTEM_DISK", "local"),
    "disks": config.M{
        "local": config.M{
            "driver": "local",
            "root":   "storage/app",
        },
        "s3": config.M{
            "driver": "s3",
            "key":    config.MustEnv("AWS_ACCESS_KEY_ID", ""),
            "secret": config.MustEnv("AWS_SECRET_ACCESS_KEY", ""),
            "region": config.MustEnv("AWS_DEFAULT_REGION", "us-east-1"),
            "bucket": config.MustEnv("AWS_BUCKET", ""),
        },
        "r2": config.M{
            "driver": "s3",
            "key":    config.MustEnv("R2_ACCESS_KEY_ID", ""),
            "secret": config.MustEnv("R2_SECRET_ACCESS_KEY", ""),
            "region": "auto",
            "bucket": config.MustEnv("R2_BUCKET", ""),
            "endpoint": config.MustEnv("R2_ENDPOINT", ""),
        },
    },
})

Providers

Local Storage

Stores files on the local filesystem. Configured with a root directory.

storage := fsys.NewLocalStorage("./storage/app")

Features: Read, Write, Delete, Exists, Rename, Copy, CreateDirectory, Open, Upload.

S3 Storage

Stores files on Amazon S3 (or S3-compatible services like Cloudflare R2).

storage := fsys.NewS3Storage(s3Config)

URLs are generated as pre-signed URLs with 15-minute expiry by default.

GCS Storage

Stores files on Google Cloud Storage.

storage := fsys.NewGCSStorage(gcsConfig)

URLs use the standard https://storage.googleapis.com/<bucket>/<path> format.

Memory Storage

In-memory storage for testing purposes.

storage := fsys.NewMemoryStorage()

All operations work in memory. GetUrl returns mock mem:// URLs. Open is not supported.