filefield

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package filefield is the runtime behind storage-backed model fields (types.File and types.Image): the code `gombit generate` writes for a resource with such a field calls it to grant uploads for the field, accept an uploaded file into a record, and describe it on reads.

A field's value is an object key in App.Storage(). Its Policy (the model's `storage` tag) is the prefix the field owns, the largest file, and the accepted types. Files are owned through storage/claims: an upload grant claims its key (pending), and a record takes a key only for an upload that passes the policy (Accept: upload.Confirm, which checks the bytes) and whose claim its transaction holds (claims.CreateWith), so a client cannot attach a file that was not uploaded for the field, or another record's file. The column's unique index backs that up. Uploads never attached stay pending until claims.Sweep removes them.

Index

Constants

View Source
const DefaultMaxBytes = 10 << 20

DefaultMaxBytes is a field's largest file unless its tag says otherwise.

View Source
const LinkTTL = 15 * time.Minute

LinkTTL is how long the signed URL of a private file in a read lives.

View Source
const MaxKeyBytes = claims.MaxKeyLen

MaxKeyBytes bounds a file column (a generated key is the prefix and 32 hex digits): it keeps the column's unique index within MySQL's limit, and is the longest key a claim holds (claims.MaxKeyLen).

View Source
const ResolveConcurrency = 8

ResolveConcurrency bounds how many rows' files a list resolves at once.

Variables

View Source
var ImageTypes = []string{"image/png", "image/jpeg", "image/gif", "image/webp"}

ImageTypes are the media types an image field accepts unless its tag says otherwise: the raster formats browsers display and http.DetectContentType recognizes (never SVG, which can carry script).

Functions

func Accept

func Accept(ctx context.Context, store storage.Storage, cl upload.Claimer, key string, p upload.Policy) error

Accept checks that key may become the value of a field with policy p in a record: nothing for no key; otherwise an upload that passes p (upload.Confirm under cl: under p's prefix, stored, within the size, of an accepted type by its bytes). A file that fails is deleted, but only while its claim is pending: never another record's file. Whether this record may take the file is decided when its transaction holds the key (claims.CreateWith fails with claims.ErrNotPending for a file another record holds, or an upload that expired).

func Claims

func Claims(db *gorm.DB, store storage.Storage, log *zap.Logger) *claims.Claims

Claims is the claims the generated handlers own their files through, over db and store, with failures to delete a released file logged to log.

func ForEach

func ForEach(ctx context.Context, n int, fn func(ctx context.Context, i int) error) error

ForEach runs fn for i in [0, n), at most ResolveConcurrency at a time, waits for all of them, and returns the first error (after which the rest see ctx canceled and are not started). The generated list uses it to resolve its rows' files in parallel rather than one storage request after another.

func KeyOf

func KeyOf[T ~string](v *T) string

KeyOf is the key of an optional file field's value ("" for nil).

func MapCreateError

func MapCreateError(ctx context.Context, err error, conflict, op string) error

MapCreateError maps the error of creating a record with files (claims.CreateWith): a file it cannot take is MapError's conflict; anything else is the database's (database.MapPersistError, with conflict and op as there).

func MapError

func MapError(ctx context.Context, err error) error

MapError maps an error of this package (or of upload, storage and claims) to a D10 error for a handler.

func Policy

func Policy(tag string, kind field.Kind, defaultPrefix string) (upload.Policy, error)

Policy parses a field's `storage` tag ("prefix=docs/file/;max_bytes=5242880; types=application/pdf,image/png") into its upload policy. kind is field.File or field.Image (which defaults to ImageTypes; a file field to any type); defaultPrefix is used when the tag names none. Unknown keys are errors, so a typo does not silently loosen a limit.

Types

type FileInfo

type FileInfo struct {
	// Key identifies the file; send it back to keep the file on a write.
	Key string `json:"key" doc:"The file's key; send it back to keep the file."`
	// Filename is the name it was uploaded with.
	Filename string `json:"filename,omitempty" doc:"The name the file was uploaded with."`
	// Size is its length in bytes.
	Size int64 `json:"size" doc:"The file's length in bytes."`
	// ContentType is its media type.
	ContentType string `json:"content_type,omitempty" doc:"The file's media type."`
	// URL downloads it: permanent for a public file, signed and short-lived
	// (LinkTTL) otherwise; empty when the store has no URLs.
	URL string `json:"url,omitempty" doc:"Where to download the file; a signed URL expires."`
	// Missing is true when the record names a file the store no longer has.
	Missing bool `json:"missing,omitempty" doc:"The record names a file the store no longer has."`
}

FileInfo is a file as a read returns it.

func Resolve

func Resolve(ctx context.Context, store storage.Storage, key string) (*FileInfo, error)

Resolve describes the file with key for a read: nil for no key; Missing when the store no longer has it.

type UploadGrant

type UploadGrant struct {
	Key    string                `json:"key" doc:"The file's key; submit it as the field's value once uploaded."`
	Upload storage.UploadRequest `json:"upload" doc:"Send the file's bytes with this request, before it expires."`
}

UploadGrant is a granted upload as the API returns it: the key to submit as the field's value, and the request that uploads the file.

func Authorize

Authorize grants the upload of one file for a field with policy p (upload.Authorize), its key claimed in cl: the client sends the returned request, then submits the grant's key as the field's value.

type UploadGrantRequest

type UploadGrantRequest struct {
	Size        int64  `json:"size" minimum:"0" doc:"The file's exact length in bytes."`
	ContentType string `json:"content_type" doc:"The file's media type."`
	Filename    string `json:"filename,omitempty" doc:"The file's name, kept for display."`
}

UploadGrantRequest is the body of a request for an upload grant.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL