Files
opencloud/services/webdav/pkg/thumbnail/cache/filecache.go
T
Jörn Friedrich Dreyer 5c3b7f8890 refactor(webdav): drive the thumbnail workflow via the push-based generator
webdav now owns the complete thumbnail pipeline: stat -> validate -> cache
check -> download -> preprocess -> generate -> cache -> respond. The
thumbnails service is used only as a stateless imagor-compatible image
resizer via its /unsafe push endpoint.

- New ThumbnailWorkflow drives the pipeline; space-scoped refs are anchored
  at the space ResourceId and downloads authenticate with the user's
  x-access-token.
- Preprocessing (audio/geogebra/text/gif) moves from the thumbnails service
  into webdav (services/webdav/pkg/preprocessor).
- Thumbnail caching moves to webdav (memory/file/s3 backends, file cache off
  by default); resolutions are snapped orientation-aware in webdav.
- Generator URL defaults to the local thumbnails service; new WEBDAV_* config
  for generator, cache and resolutions.
- Acceptance tests updated for the new sizing/processor behavior.
2026-09-04 23:05:11 +02:00

79 lines
1.4 KiB
Go

package cache
import (
"errors"
"io/fs"
"os"
"path/filepath"
)
// FileCache stores thumbnails on the local filesystem using hierarchical directories.
type FileCache struct {
dir string
}
func NewFileCache(dir string) *FileCache {
return &FileCache{dir: dir}
}
// The cache key is already a hierarchical relative path (built to match main's
// BuildKey layout), so the on-disk location is simply the cache dir joined with it.
func (c *FileCache) Get(key string) ([]byte, error) {
path := filepath.Join(c.dir, key)
data, err := os.ReadFile(path)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, ErrCacheMiss
}
return nil, err
}
result := make([]byte, len(data))
copy(result, data)
return result, nil
}
func (c *FileCache) Put(key string, data []byte) error {
imgPath := filepath.Join(c.dir, key)
dir := filepath.Dir(imgPath)
if _, err := os.Stat(imgPath); err == nil {
return nil
}
if err := os.MkdirAll(dir, 0700); err != nil {
return err
}
f, err := os.CreateTemp(dir, "tmpthumb")
if err != nil {
return err
}
tempPath := f.Name()
if _, err := f.Write(data); err != nil {
f.Close()
os.Remove(tempPath)
return err
}
if err := f.Sync(); err != nil {
f.Close()
os.Remove(tempPath)
return err
}
if err := f.Close(); err != nil {
os.Remove(tempPath)
return err
}
if err := os.Rename(tempPath, imgPath); err != nil {
os.Remove(tempPath)
return err
}
return nil
}