Skip to content

Commit

Permalink
fix: delete cached previews when deleting file
Browse files Browse the repository at this point in the history
  • Loading branch information
o1egl committed Jul 28, 2020
1 parent c9340af commit f5d02cd
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 25 deletions.
2 changes: 1 addition & 1 deletion diskcache/file_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (f *FileCache) Delete(ctx context.Context, key string) error {
defer mu.Unlock()

fileName := f.getFileName(key)
if err := f.fs.Remove(fileName); err != nil && err != os.ErrNotExist {
if err := f.fs.Remove(fileName); err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func NewHandler(imgSvc ImgService, fileCache FileCache, store *storage.Storage,
users.Handle("/{id:[0-9]+}", monkey(userDeleteHandler, "")).Methods("DELETE")

api.PathPrefix("/resources").Handler(monkey(resourceGetHandler, "/api/resources")).Methods("GET")
api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler, "/api/resources")).Methods("DELETE")
api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler(fileCache), "/api/resources")).Methods("DELETE")
api.PathPrefix("/resources").Handler(monkey(resourcePostPutHandler, "/api/resources")).Methods("POST")
api.PathPrefix("/resources").Handler(monkey(resourcePostPutHandler, "/api/resources")).Methods("PUT")
api.PathPrefix("/resources").Handler(monkey(resourcePatchHandler, "/api/resources")).Methods("PATCH")
Expand Down
32 changes: 21 additions & 11 deletions http/preview.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:generate go-enum --sql --marshal --names --file $GOFILE
package http

import (
Expand All @@ -13,10 +14,13 @@ import (
"github.com/filebrowser/filebrowser/v2/img"
)

const (
sizeThumb = "thumb"
sizeBig = "big"
/*
ENUM(
thumb
big
)
*/
type PreviewSize int

type ImgService interface {
FormatFromExtension(ext string) (img.Format, error)
Expand All @@ -26,6 +30,7 @@ type ImgService interface {
type FileCache interface {
Store(ctx context.Context, key string, value []byte) error
Load(ctx context.Context, key string) ([]byte, bool, error)
Delete(ctx context.Context, key string) error
}

func previewHandler(imgSvc ImgService, fileCache FileCache, enableThumbnails, resizePreview bool) handleFunc {
Expand All @@ -34,9 +39,10 @@ func previewHandler(imgSvc ImgService, fileCache FileCache, enableThumbnails, re
return http.StatusAccepted, nil
}
vars := mux.Vars(r)
size := vars["size"]
if size != sizeBig && size != sizeThumb {
return http.StatusNotImplemented, nil

previewSize, err := ParsePreviewSize(vars["size"])
if err != nil {
return http.StatusBadRequest, err
}

file, err := files.NewFileInfo(files.FileOptions{
Expand All @@ -54,15 +60,15 @@ func previewHandler(imgSvc ImgService, fileCache FileCache, enableThumbnails, re

switch file.Type {
case "image":
return handleImagePreview(w, r, imgSvc, fileCache, file, size, enableThumbnails, resizePreview)
return handleImagePreview(w, r, imgSvc, fileCache, file, previewSize, enableThumbnails, resizePreview)
default:
return http.StatusNotImplemented, fmt.Errorf("can't create preview for %s type", file.Type)
}
})
}

func handleImagePreview(w http.ResponseWriter, r *http.Request, imgSvc ImgService, fileCache FileCache,
file *files.FileInfo, size string, enableThumbnails, resizePreview bool) (int, error) {
file *files.FileInfo, previewSize PreviewSize, enableThumbnails, resizePreview bool) (int, error) {
format, err := imgSvc.FormatFromExtension(file.Extension)
if err != nil {
// Unsupported extensions directly return the raw data
Expand All @@ -72,7 +78,7 @@ func handleImagePreview(w http.ResponseWriter, r *http.Request, imgSvc ImgServic
return errToStatus(err), err
}

cacheKey := file.Path + size
cacheKey := previewCacheKey(file.Path, previewSize)
cachedFile, ok, err := fileCache.Load(r.Context(), cacheKey)
if err != nil {
return errToStatus(err), err
Expand All @@ -95,11 +101,11 @@ func handleImagePreview(w http.ResponseWriter, r *http.Request, imgSvc ImgServic
)

switch {
case size == sizeBig && resizePreview && format != img.FormatGif:
case previewSize == PreviewSizeBig && resizePreview && format != img.FormatGif:
width = 1080
height = 1080
options = append(options, img.WithMode(img.ResizeModeFit), img.WithQuality(img.QualityMedium))
case size == sizeThumb && enableThumbnails:
case previewSize == PreviewSizeThumb && enableThumbnails:
width = 128
height = 128
options = append(options, img.WithMode(img.ResizeModeFill), img.WithQuality(img.QualityLow), img.WithFormat(img.FormatJpeg))
Expand All @@ -125,3 +131,7 @@ func handleImagePreview(w http.ResponseWriter, r *http.Request, imgSvc ImgServic

return 0, nil
}

func previewCacheKey(fPath string, previewSize PreviewSize) string {
return fPath + previewSize.String()
}
100 changes: 100 additions & 0 deletions http/preview_enum.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 33 additions & 12 deletions http/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,42 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
return renderJSON(w, r, file)
})

var resourceDeleteHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
if r.URL.Path == "/" || !d.user.Perm.Delete {
return http.StatusForbidden, nil
}
func resourceDeleteHandler(fileCache FileCache) handleFunc {
return withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
if r.URL.Path == "/" || !d.user.Perm.Delete {
return http.StatusForbidden, nil
}

err := d.RunHook(func() error {
return d.user.Fs.RemoveAll(r.URL.Path)
}, "delete", r.URL.Path, "", d.user)
file, err := files.NewFileInfo(files.FileOptions{
Fs: d.user.Fs,
Path: r.URL.Path,
Modify: d.user.Perm.Modify,
Expand: true,
Checker: d,
})
if err != nil {
return errToStatus(err), err
}

if err != nil {
return errToStatus(err), err
}
// delete thumbnails
for _, previewSizeName := range PreviewSizeNames() {
size, _ := ParsePreviewSize(previewSizeName)
if err := fileCache.Delete(r.Context(), previewCacheKey(file.Path, size)); err != nil {
return errToStatus(err), err
}
}

return http.StatusOK, nil
})
err = d.RunHook(func() error {
return d.user.Fs.RemoveAll(r.URL.Path)
}, "delete", r.URL.Path, "", d.user)

if err != nil {
return errToStatus(err), err
}

return http.StatusOK, nil
})
}

var resourcePostPutHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
if !d.user.Perm.Create && r.Method == http.MethodPost {
Expand Down

0 comments on commit f5d02cd

Please sign in to comment.