package http import ( "fmt" "image" "net/http" "github.com/disintegration/imaging" "github.com/gorilla/mux" "github.com/filebrowser/filebrowser/v2/files" ) const ( sizeThumb = "thumb" sizeBig = "big" ) type imageProcessor func(src image.Image) (image.Image, error) var previewHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { if !d.user.Perm.Download { return http.StatusAccepted, nil } vars := mux.Vars(r) size := vars["size"] if size != sizeBig && size != sizeThumb { return http.StatusNotImplemented, nil } file, err := files.NewFileInfo(files.FileOptions{ Fs: d.user.Fs, Path: "/" + vars["path"], Modify: d.user.Perm.Modify, Expand: true, Checker: d, }) if err != nil { return errToStatus(err), err } setContentDisposition(w, r, file) switch file.Type { case "image": return handleImagePreview(w, r, file, size) default: return http.StatusNotImplemented, fmt.Errorf("can't create preview for %s type", file.Type) } }) func handleImagePreview(w http.ResponseWriter, r *http.Request, file *files.FileInfo, size string) (int, error) { format, err := imaging.FormatFromExtension(file.Extension) if err != nil { // Unsupported extensions directly return the raw data if err == imaging.ErrUnsupportedFormat { return rawFileHandler(w, r, file) } return errToStatus(err), err } fd, err := file.Fs.Open(file.Path) if err != nil { return errToStatus(err), err } defer fd.Close() if format == imaging.GIF && size == sizeBig { if _, err := rawFileHandler(w, r, file); err != nil { //nolint: govet return errToStatus(err), err } return 0, nil } var imgProcessor imageProcessor switch size { case sizeBig: imgProcessor = func(img image.Image) (image.Image, error) { return imaging.Fit(img, 1080, 1080, imaging.Lanczos), nil } case sizeThumb: imgProcessor = func(img image.Image) (image.Image, error) { return imaging.Thumbnail(img, 128, 128, imaging.Box), nil } default: return http.StatusBadRequest, fmt.Errorf("unsupported preview size %s", size) } img, err := imaging.Decode(fd, imaging.AutoOrientation(true)) if err != nil { return errToStatus(err), err } img, err = imgProcessor(img) if err != nil { return errToStatus(err), err } if imaging.Encode(w, img, format) != nil { return errToStatus(err), err } return 0, nil }