fix: serve media previews with browser-compatible content
This commit is contained in:
+35
-8
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user