Documentation
¶
Overview ¶
Package file provides a local-filesystem Storage backend for Den.
Importing this package for its side effect registers the "file://" scheme with storage.OpenURL:
import _ "github.com/oliverandrich/den/storage/file"
s, err := storage.OpenURL("file:///data/media?url_prefix=/media")
The DSN follows the SQLAlchemy/JDBC convention: three slashes for a relative path, four for an absolute path (one leading slash is stripped on parse so standard URL libraries see the whole location in the path component).
For direct construction without the registry, call New; it takes the filesystem path literally.
Index ¶
- type Storage
- func (s *Storage) Close() error
- func (s *Storage) Delete(_ context.Context, a document.Attachment) error
- func (s *Storage) Open(_ context.Context, a document.Attachment) (io.ReadCloser, error)
- func (s *Storage) OpenSeekable(_ context.Context, a document.Attachment) (io.ReadSeekCloser, error)
- func (s *Storage) Store(_ context.Context, r io.Reader, ext, mime string) (document.Attachment, error)
- func (s *Storage) URL(a document.Attachment) string
- func (s *Storage) URLPrefix() string
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Storage ¶
type Storage struct {
// contains filtered or unexported fields
}
Storage keeps attachment bytes on the local filesystem rooted at a configurable directory. Paths are year/month-bucketed with a filename derived from the first 16 hex digits of the content's SHA-256 plus the caller-supplied extension.
Example produced path: "2026/04/abc123def4567890.jpg".
When two calls upload identical bytes in the same month, the path collides and the second Store short-circuits, returning the existing path without duplicating the file on disk. Content-addressing with the unique StoragePath index on the Den side gives atomic deduplication across application restarts.
Path traversal in Open/Delete is prevented by os.Root (Go 1.24+), which refuses any path that escapes the configured root directory.
func New ¶
New creates the root directory if missing and returns a Storage bound to it. urlPrefix is the HTTP path prefix under which files are served (for example "/media"); a trailing slash is trimmed.
func (*Storage) Delete ¶
Delete implements den.Storage. Missing paths are treated as success.
func (*Storage) Open ¶
func (s *Storage) Open(_ context.Context, a document.Attachment) (io.ReadCloser, error)
Open implements den.Storage.
func (*Storage) OpenSeekable ¶ added in v0.11.2
func (s *Storage) OpenSeekable(_ context.Context, a document.Attachment) (io.ReadSeekCloser, error)
OpenSeekable implements den.SeekableStorage — local files are backed by *os.File which natively supports Seek, so http.ServeContent can use the returned handle for Range and If-None-Match handling.
func (*Storage) Store ¶
func (s *Storage) Store(_ context.Context, r io.Reader, ext, mime string) (document.Attachment, error)
Store implements den.Storage.
func (*Storage) URL ¶
func (s *Storage) URL(a document.Attachment) string
URL implements den.Storage.
func (*Storage) URLPrefix ¶
URLPrefix returns the HTTP path prefix under which this storage's files are served (without a trailing slash). HTTP-layer packages use this to mount a serving handler on the same route the URL method produces.
Remote Storage backends that return absolute URLs (S3, GCS, …) do NOT implement this method — HTTP-layer packages can type-assert on a "URLPrefix() string" interface to decide whether to register a local serving handler at all.