fix: match CHFS preview and listing behavior

This commit is contained in:
OpenClaw Agent
2026-09-21 18:08:35 +08:00
parent 3d65a94429
commit 871e72277c
5 changed files with 48 additions and 9 deletions
+1 -1
View File
@@ -89,7 +89,7 @@ func main() {
if len(cfg.Path) == 1 {
store = storage.Local{Root: root}
}
srv := &api.Server{Store: store, Auth: mgr, Sessions: map[string]*auth.Account{}, SessionExpiry: map[string]time.Time{}, SessionTimeout: cfg.SessionTimeout, WebDAVRoot: root, Allow: cfg.Allow, MultiRoot: len(cfg.Path) > 1, RemoveMode: cfg.FileRemove, Log: opslog.New(cfg.Log)}
srv := &api.Server{Store: store, Auth: mgr, Sessions: map[string]*auth.Account{}, SessionExpiry: map[string]time.Time{}, SessionTimeout: cfg.SessionTimeout, WebDAVRoot: root, Allow: cfg.Allow, MultiRoot: len(cfg.Path) > 1, RemoveMode: cfg.FileRemove, ImagePreview: cfg.ImagePreview, Log: opslog.New(cfg.Log)}
addr := ":" + itoa(cfg.Port)
log.Printf("chfs-ng listening on %s root=%s removeMode=%d", addr, filepath.Clean(root), cfg.FileRemove)
if cfg.SSLCert != "" && cfg.SSLKey != "" {
+1
View File
@@ -4,6 +4,7 @@ go 1.22
require (
github.com/Bios-Marcel/wastebasket v0.0.3
github.com/anthonynsimon/bild v0.14.0
github.com/emersion/go-webdav v0.7.0
github.com/golang-jwt/jwt/v4 v4.5.2
)
+2
View File
@@ -1,5 +1,7 @@
github.com/Bios-Marcel/wastebasket v0.0.3 h1:gyuMcoDav6n+sdynn9TDl1NN7GOAnoy227JErVSW3RM=
github.com/Bios-Marcel/wastebasket v0.0.3/go.mod h1:FChzXi1izqzdPb6BiNZmcZLGyTYiT61iGx9Rxx9GNeI=
github.com/anthonynsimon/bild v0.14.0 h1:IFRkmKdNdqmexXHfEU7rPlAmdUZ8BDZEGtGHDnGWync=
github.com/anthonynsimon/bild v0.14.0/go.mod h1:hcvEAyBjTW69qkKJTfpcDQ83sSZHxwOunsseDfeQhUs=
github.com/emersion/go-ical v0.0.0-20240127095438-fc1c9d8fb2b6/go.mod h1:BEksegNspIkjCQfmzWgsgbu6KdeJ/4LwUZs7DMBzjzw=
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
github.com/emersion/go-webdav v0.7.0 h1:cp6aBWXBf8Sjzguka9VJarr4XTkGc2IHxXI1Gq3TKpA=
+37 -7
View File
@@ -2,9 +2,14 @@ package api
import (
"archive/zip"
"bytes"
"context"
"encoding/json"
"fmt"
"image"
_ "image/gif"
_ "image/jpeg"
"image/png"
"io"
"mime/multipart"
"net"
@@ -19,6 +24,7 @@ import (
"chfs-ng/internal/auth"
"chfs-ng/internal/opslog"
"chfs-ng/internal/storage"
"github.com/anthonynsimon/bild/transform"
"github.com/emersion/go-webdav"
)
@@ -34,6 +40,7 @@ type Server struct {
Allow string
MultiRoot bool
RemoveMode int
ImagePreview bool
Log *opslog.Logger
}
type fileInfo struct {
@@ -463,7 +470,7 @@ func (s *Server) search(w http.ResponseWriter, r *http.Request) {
return
}
needle := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("str")))
var out []fileInfo
out := make([]fileInfo, 0)
var walk func(string) error
walk = func(dir string) error {
items, err := s.Store.List(dir)
@@ -502,16 +509,39 @@ func (s *Server) shared(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) preview(w http.ResponseWriter, r *http.Request) {
if !account(r, s).MaskFor(strings.Trim(r.URL.Query().Get("file"), "/")).HasRead() {
http.Error(w, "forbidden", 403)
return
}
file := strings.Trim(r.URL.Query().Get("file"), "/")
file := strings.Trim(strings.ReplaceAll(r.URL.Query().Get("file"), "\\", "/"), "/")
if file == "" {
http.Error(w, "file required", 400)
return
}
s.serveFile(w, r, file, false)
if !account(r, s).MaskFor(file).HasRead() {
http.Error(w, "forbidden", 403)
return
}
if !s.ImagePreview {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
return
}
f, err := s.Store.Open(file)
if err != nil {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
return
}
defer f.Close()
src, _, err := image.Decode(f)
if err != nil {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
return
}
thumb := transform.Resize(src, 64, 64, transform.Linear)
var buf bytes.Buffer
if err := png.Encode(&buf, thumb); err != nil {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
return
}
w.Header().Set("Cache-Control", "max-age=2592000")
w.Header().Set("Content-Type", "image/png")
_, _ = w.Write(buf.Bytes())
}
func (s *Server) fileHandler(w http.ResponseWriter, r *http.Request) {
+7 -1
View File
@@ -7,6 +7,7 @@ import (
"io/fs"
"os"
"path/filepath"
"sort"
"strings"
"syscall"
"time"
@@ -258,7 +259,12 @@ func (s Local) List(path string) ([]os.FileInfo, error) {
return nil, e
}
defer f.Close()
return f.Readdir(-1)
items, err := f.Readdir(-1)
if err != nil {
return nil, err
}
sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() })
return items, nil
}
var _ fs.FS