Fix download: serve file manually to avoid http.ServeFile header conflicts

This commit is contained in:
James 2026-02-12 17:50:12 -05:00
parent 99b39ee737
commit a1d156bbd5
1 changed files with 26 additions and 22 deletions

48
main.go
View File

@ -277,36 +277,40 @@ func servePDF(w http.ResponseWriter, r *http.Request) {
hash := chi.URLParam(r, "hash") hash := chi.URLParam(r, "hash")
download := r.URL.Query().Get("download") == "1" download := r.URL.Query().Get("download") == "1"
// Try PDF first, then TXT // Try PDF first, then TXT, then bare
for _, ext := range []string{".pdf", ".txt"} { for _, ext := range []string{".pdf", ".txt", ""} {
path := filepath.Join(storeDir, hash+ext) path := filepath.Join(storeDir, hash+ext)
if _, err := os.Stat(path); err == nil { fi, err := os.Stat(path)
if ext == ".pdf" { if err != nil {
w.Header().Set("Content-Type", "application/pdf") continue
} else {
w.Header().Set("Content-Type", "text/plain")
}
if download {
filename := hash + ext
if doc, err := GetDocument(hash); err == nil && doc.Title != "" {
filename = sanitizeFilename(doc.Title) + ext
}
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
}
http.ServeFile(w, r, path)
return
} }
}
// Try without extension
path := filepath.Join(storeDir, hash)
if _, err := os.Stat(path); err == nil {
if download { if download {
filename := hash filename := hash + ext
if doc, err := GetDocument(hash); err == nil && doc.Title != "" { if doc, err := GetDocument(hash); err == nil && doc.Title != "" {
filename = sanitizeFilename(doc.Title) filename = sanitizeFilename(doc.Title)
if ext != "" && !strings.HasSuffix(strings.ToLower(filename), ext) {
filename += ext
}
} }
f, err := os.Open(path)
if err != nil {
http.Error(w, "Cannot read file", http.StatusInternalServerError)
return
}
defer f.Close()
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename)) w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
w.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size()))
io.Copy(w, f)
return
}
// Inline viewing
if ext == ".pdf" || ext == "" {
w.Header().Set("Content-Type", "application/pdf")
} else {
w.Header().Set("Content-Type", "text/plain")
} }
http.ServeFile(w, r, path) http.ServeFile(w, r, path)
return return