fix: serve media previews with browser-compatible content

This commit is contained in:
OpenClaw Agent
2026-09-22 05:33:34 +08:00
parent 6b86eb4185
commit e3fef60d60
2 changed files with 38 additions and 11 deletions
+35 -8
View File
@@ -96,6 +96,7 @@ func (s *Server) Handler() http.Handler {
mux.HandleFunc("/chfs/shared", s.shared)
mux.HandleFunc("/chfs/shared/", s.shared)
mux.HandleFunc("/chfs/preview", s.preview)
mux.HandleFunc("/chfs/thumbnail", s.thumbnail)
mux.HandleFunc("/asset/api.html", s.apiDoc)
mux.HandleFunc("/", s.fileHandler)
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -1131,36 +1132,62 @@ func (s *Server) preview(w http.ResponseWriter, r *http.Request) {
}
file := strings.Trim(strings.ReplaceAll(rawFile, "\\", "/"), "/")
if file == "" {
http.Error(w, "file required", 400)
http.Error(w, "file required", http.StatusBadRequest)
return
}
if !account(r, s).MaskFor(file).HasRead() {
writeJSONError(w, http.StatusForbidden, "has no privilege")
return
}
if !s.ImagePreview {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
fi, err := s.Store.Stat(file)
if err != nil || fi.IsDir() {
http.NotFound(w, r)
return
}
f, err := s.Store.Open(file)
if err != nil {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
http.NotFound(w, r)
return
}
defer f.Close()
if ct := mime.TypeByExtension(strings.ToLower(path.Ext(fi.Name()))); ct != "" {
w.Header().Set("Content-Type", ct)
}
w.Header().Set("Content-Disposition", mime.FormatMediaType("inline", map[string]string{"filename": fi.Name()}))
w.Header().Set("Cache-Control", "private, max-age=60")
http.ServeContent(w, r, fi.Name(), fi.ModTime(), f)
}
func (s *Server) thumbnail(w http.ResponseWriter, r *http.Request) {
rawFile := r.URL.Query().Get("file")
if unsafePath(rawFile) {
writeJSONError(w, http.StatusBadRequest, "invalid parameter")
return
}
file := strings.Trim(strings.ReplaceAll(rawFile, "\\", "/"), "/")
if file == "" || !account(r, s).MaskFor(file).HasRead() || !s.ImagePreview {
http.Error(w, "thumbnail unavailable", http.StatusForbidden)
return
}
f, err := s.Store.Open(file)
if err != nil {
http.NotFound(w, r)
return
}
defer f.Close()
src, _, err := image.Decode(f)
if err != nil {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
http.Error(w, "thumbnail unavailable", http.StatusUnsupportedMediaType)
return
}
thumb := transform.Resize(src, 64, 64, transform.Linear)
thumb := transform.Resize(src, 320, 240, transform.Linear)
var buf bytes.Buffer
if err := png.Encode(&buf, thumb); err != nil {
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
http.Error(w, "thumbnail unavailable", http.StatusInternalServerError)
return
}
w.Header().Set("Cache-Control", "max-age=2592000")
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Cache-Control", "private, max-age=300")
_, _ = w.Write(buf.Bytes())
}