From 274dfd244dd808dda4e9373de4775f1e185e6281 Mon Sep 17 00:00:00 2001 From: Cy Allen Scott Date: Fri, 22 Apr 2022 14:58:34 -0400 Subject: [PATCH] resolves gh-1916 --- files/file.go | 82 ++++++++++++++++++++++++++---------------------- http/preview.go | 24 ++++++++------ http/resource.go | 59 ++++++++-------------------------- 3 files changed, 72 insertions(+), 93 deletions(-) diff --git a/files/file.go b/files/file.go index e0ef153d..b9daa8e3 100644 --- a/files/file.go +++ b/files/file.go @@ -56,11 +56,6 @@ type FileOptions struct { Content bool } -type FileThumbnail struct { - Dir string - Path string -} - // NewFileInfo creates a File object from a path and a given user. This File // object will be automatically filled depending on if it is a directory // or a file. If it's a video file, it will also detect any subtitles. @@ -91,32 +86,16 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { return file, err } -func NewThumbnailInfo(opts FileOptions) (*FileInfo, error) { - return NewFileInfo(FileOptions{ - Fs: opts.Fs, - Path: NewFileThumbnail(opts).Path, - Modify: opts.Modify, - Expand: opts.Expand, - ReadHeader: opts.ReadHeader, - Checker: opts.Checker, - }) -} +func ThumbnailPath(path string) string { + dir := os.Getenv("XDG_CACHE_HOME") -func NewFileThumbnail(opts FileOptions) FileThumbnail { - dir, name := filepath.Split(opts.Path) - - hash := md5.Sum([]byte(name)) - - thumbnailName := hex.EncodeToString(hash[:]) + ".jpg" - - thumbnailPath := path.Join(dir, ".filebrowser", thumbnailName) - - dir, _ = filepath.Split(thumbnailPath) - - return FileThumbnail{ - Dir: dir, - Path: thumbnailPath, + if dir == "" { + dir = filepath.Join(os.Getenv("HOME"), ".cache") } + + hash := md5.Sum([]byte(path)) + + return filepath.Join(dir, "thumbnails", "xx-large", hex.EncodeToString(hash[:])+".png") } func stat(opts FileOptions) (*FileInfo, error) { @@ -237,6 +216,37 @@ func (i *FileInfo) RealPath() string { return i.Path } +func (i *FileInfo) Thumbnail() (*FileInfo, error) { + + realPath := i.RealPath() + + path := ThumbnailPath(realPath) + + dir, _ := filepath.Split(path) + + info, err := os.Stat(path) + + if err != nil { + return nil, err + } + + file := &FileInfo{ + Fs: i.Fs, + Dir: dir, + Path: path, + Name: info.Name(), + ModTime: info.ModTime(), + Mode: info.Mode(), + IsDir: info.IsDir(), + Size: info.Size(), + Extension: filepath.Ext(info.Name()), + Token: i.Token, + Type: "image", + } + + return file, err +} + //nolint:goconst //TODO: use constants func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error { @@ -263,7 +273,6 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error { switch { case strings.HasPrefix(mimetype, "video"): i.Type = "video" - i.detectThumbnail() i.detectSubtitles() return nil case strings.HasPrefix(mimetype, "audio"): @@ -343,14 +352,7 @@ func (i *FileInfo) detectSubtitles() { } func (i *FileInfo) detectThumbnail() { - dir, name := filepath.Split(i.RealPath()) - - hash := md5.Sum([]byte(name)) - thumbnailName := hex.EncodeToString(hash[:]) - - path := path.Join(dir, ".filebrowser", thumbnailName+".jpg") - - _, err := os.Stat(path) + _, err := i.Thumbnail() if err == nil { i.IsThumbsEnabled = true @@ -410,6 +412,10 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { if err != nil { return err } + + if !file.IsThumbsEnabled { + file.detectThumbnail() + } } listing.Items = append(listing.Items, file) diff --git a/http/preview.go b/http/preview.go index a0cd4441..db01ee3d 100644 --- a/http/preview.go +++ b/http/preview.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "net/http" + "os" "github.com/gorilla/mux" @@ -59,16 +60,9 @@ func previewHandler(imgSvc ImgService, fileCache FileCache, enableThumbnails, re setContentDisposition(w, r, file) - thumbnail, err := files.NewThumbnailInfo(files.FileOptions{ - Fs: d.user.Fs, - Path: "/" + vars["path"], - Modify: d.user.Perm.Modify, - Expand: true, - ReadHeader: d.server.TypeDetectionByHeader, - Checker: d, - }) + thumbnail, err := file.Thumbnail() if err == nil && thumbnail != nil { - return rawFileHandler(w, r, thumbnail) + return handleThumbnail(w, r, thumbnail) } switch file.Type { @@ -80,6 +74,18 @@ func previewHandler(imgSvc ImgService, fileCache FileCache, enableThumbnails, re }) } +func handleThumbnail(w http.ResponseWriter, r *http.Request, file *files.FileInfo) (int, error) { + fd, err := os.Open(file.Path) + if err != nil { + return http.StatusInternalServerError, err + } + defer fd.Close() + + w.Header().Set("Cache-Control", "private") + http.ServeContent(w, r, file.Name, file.ModTime, fd) + return 0, nil +} + func handleImagePreview( w http.ResponseWriter, r *http.Request, diff --git a/http/resource.go b/http/resource.go index 09e403ee..60c8afd4 100644 --- a/http/resource.go +++ b/http/resource.go @@ -77,14 +77,7 @@ func resourceDeleteHandler(fileCache FileCache) handleFunc { return errToStatus(err), err } - thumbnail, err := files.NewThumbnailInfo(files.FileOptions{ - Fs: d.user.Fs, - Path: r.URL.Path, - Modify: d.user.Perm.Modify, - Expand: false, - ReadHeader: d.server.TypeDetectionByHeader, - Checker: d, - }) + thumbnail, err := file.Thumbnail() if err == nil && thumbnail != nil { d.user.Fs.RemoveAll(thumbnail.Path) } @@ -311,30 +304,23 @@ func patchAction(ctx context.Context, action, src, dst string, d *data, fileCach return errors.ErrPermissionDenied } - srcThumbnail, err := files.NewThumbnailInfo(files.FileOptions{ + file, err := files.NewFileInfo(files.FileOptions{ Fs: d.user.Fs, Path: src, Modify: d.user.Perm.Modify, Expand: false, - ReadHeader: d.server.TypeDetectionByHeader, + ReadHeader: false, Checker: d, }) + if err != nil { + return err + } + + srcThumbnail, err := file.Thumbnail() if err == nil && srcThumbnail != nil { - destThumbnail := files.NewFileThumbnail(files.FileOptions{ - Fs: d.user.Fs, - Path: dst, - Modify: d.user.Perm.Modify, - Expand: false, - ReadHeader: d.server.TypeDetectionByHeader, - Checker: d, - }) + destThumbnail := files.ThumbnailPath(dst) - _, err := os.Stat(destThumbnail.Dir) - if err != nil { - fileutils.CreateDir(d.user.Fs, srcThumbnail.Dir, destThumbnail.Dir) - } - - fileutils.Copy(d.user.Fs, srcThumbnail.Path, destThumbnail.Path) + fileutils.Copy(d.user.Fs, srcThumbnail.Path, destThumbnail) } return fileutils.Copy(d.user.Fs, src, dst) @@ -363,30 +349,11 @@ func patchAction(ctx context.Context, action, src, dst string, d *data, fileCach return err } - srcThumbnail, err := files.NewThumbnailInfo(files.FileOptions{ - Fs: d.user.Fs, - Path: src, - Modify: d.user.Perm.Modify, - Expand: false, - ReadHeader: d.server.TypeDetectionByHeader, - Checker: d, - }) + srcThumbnail, err := file.Thumbnail() if err == nil && srcThumbnail != nil { - destThumbnail := files.NewFileThumbnail(files.FileOptions{ - Fs: d.user.Fs, - Path: dst, - Modify: d.user.Perm.Modify, - Expand: false, - ReadHeader: d.server.TypeDetectionByHeader, - Checker: d, - }) + destThumbnail := files.ThumbnailPath(dst) - _, err := os.Stat(destThumbnail.Dir) - if err != nil { - fileutils.CreateDir(d.user.Fs, srcThumbnail.Dir, destThumbnail.Dir) - } - - fileutils.MoveFile(d.user.Fs, srcThumbnail.Path, destThumbnail.Path) + fileutils.MoveFile(d.user.Fs, srcThumbnail.Path, destThumbnail) } return fileutils.MoveFile(d.user.Fs, src, dst)