feat: complete guest shared download flow
This commit is contained in:
+32
-9
@@ -14,6 +14,7 @@ import (
|
||||
_ "image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -1039,6 +1040,18 @@ func (s *Server) search(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, map[string]any{"virtualRoot": 0, "currentMask": permString(rootMask), "files": out})
|
||||
}
|
||||
|
||||
func sharedPath(parts ...string) string {
|
||||
encoded := make([]string, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
encoded = append(encoded, url.PathEscape(part))
|
||||
}
|
||||
return "/chfs/shared/" + strings.Join(encoded, "/")
|
||||
}
|
||||
|
||||
func attachmentDisposition(name string) string {
|
||||
return mime.FormatMediaType("attachment", map[string]string{"filename": name})
|
||||
}
|
||||
|
||||
func (s *Server) shared(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/chfs/shared" {
|
||||
location := "shared/"
|
||||
@@ -1061,33 +1074,43 @@ func (s *Server) shared(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if fi.IsDir() {
|
||||
w.Header().Set("Content-Disposition", `attachment;filename="shared"`)
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Header().Set("Cache-Control", "private, no-cache")
|
||||
w.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat))
|
||||
if r.Method == http.MethodHead {
|
||||
return
|
||||
}
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
items, err := s.Store.List(p)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
_, _ = io.WriteString(w, "<pre>\n")
|
||||
_, _ = io.WriteString(w, "<!doctype html><meta charset=\"utf-8\"><title>CHFS Shared</title><style>body{font:15px system-ui,sans-serif;max-width:760px;margin:40px auto;padding:0 18px}a{display:block;padding:10px 0;text-decoration:none}</style><h2>共享文件</h2><p>"+html.EscapeString(p)+"</p>")
|
||||
for _, item := range items {
|
||||
name := item.Name()
|
||||
href := url.PathEscape(name)
|
||||
child := path.Join(p, item.Name())
|
||||
if !account(r, s).MaskForEntry(child).HasRead() {
|
||||
continue
|
||||
}
|
||||
href := sharedPath(strings.Split(strings.Trim(child, "/"), "/")...)
|
||||
if item.IsDir() {
|
||||
href += "/"
|
||||
}
|
||||
_, _ = fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", href, html.EscapeString(name)+func() string {
|
||||
_, _ = fmt.Fprintf(w, "<a href=\"%s\">%s%s</a>", html.EscapeString(href), html.EscapeString(item.Name()), func() string {
|
||||
if item.IsDir() {
|
||||
return "/"
|
||||
}
|
||||
return ""
|
||||
}())
|
||||
}
|
||||
_, _ = io.WriteString(w, "</pre>\n")
|
||||
_, _ = io.WriteString(w, "</body></html>")
|
||||
return
|
||||
}
|
||||
if r.Method != http.MethodGet {
|
||||
http.NotFound(w, r)
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
f, err := s.Store.Open(p)
|
||||
@@ -1096,7 +1119,7 @@ func (s *Server) shared(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment;filename="%s"`, fi.Name()))
|
||||
w.Header().Set("Content-Disposition", attachmentDisposition(fi.Name()))
|
||||
http.ServeContent(w, r, fi.Name(), fi.ModTime(), f)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user