b988b4b15e
- fix: replace multipart form parsing with streaming multipart reads and apply request body limits when max_upload_size is configured. - refactor: route uploads through staging paths before promotion to long-term data paths, keeping incomplete uploads out of durable storage records. - test: cover oversized uploads, unlimited uploads, staged cleanup, and local storage promotion boundaries. - docs: document the staged upload model and multipart parent_id query parameter.
31 lines
1.1 KiB
Go
31 lines
1.1 KiB
Go
// Package storage provides an abstraction layer for file content persistence.
|
|
package storage
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
)
|
|
|
|
// StorageBackend abstracts where file content is staged, promoted, read, and
|
|
// deleted. Paths passed to all methods are relative to the backend's root and
|
|
// must not contain path traversal sequences.
|
|
type StorageBackend interface {
|
|
// SaveStaged writes the contents of reader to a staging path, creating
|
|
// parent directories as needed. It returns the number of bytes written.
|
|
SaveStaged(ctx context.Context, path string, reader io.Reader) (int64, error)
|
|
|
|
// PromoteStaged moves a staged object to its final path.
|
|
PromoteStaged(ctx context.Context, stagedPath, finalPath string) error
|
|
|
|
// Open returns a reader for the file at path. The caller must close the
|
|
// returned ReadCloser.
|
|
Open(ctx context.Context, path string) (io.ReadCloser, error)
|
|
|
|
// DeleteStaged removes a staged object. It is idempotent.
|
|
DeleteStaged(ctx context.Context, path string) error
|
|
|
|
// Delete removes the file at path. It is idempotent — deleting a
|
|
// non-existent file is not an error.
|
|
Delete(ctx context.Context, path string) error
|
|
}
|