package web import ( "fmt" "net/http" "os" "path/filepath" "time" ) func (s *Server) handleExportPage(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := exportPage.ExecuteTemplate(w, "base", nil); err != nil { s.serverError(w, "render export page", err) } } func (s *Server) handleExportDB(w http.ResponseWriter, r *http.Request) { includeBlobs := r.URL.Query().Get("blobs") != "false" // default: include // Snapshot to a fresh temp path (VACUUM INTO requires the file not exist). tmpDir, err := os.MkdirTemp("", "hsa-export-") if err != nil { s.serverError(w, "export tempdir", err) return } defer os.RemoveAll(tmpDir) snapPath := filepath.Join(tmpDir, "snapshot.db") if err := s.store.SnapshotTo(snapPath, includeBlobs); err != nil { s.serverError(w, "export snapshot", err) return } f, err := os.Open(snapPath) if err != nil { s.serverError(w, "open snapshot", err) return } defer f.Close() suffix := "" if !includeBlobs { suffix = "-metadata" } filename := fmt.Sprintf("hsa-export-%s%s.db", time.Now().Format(dateLayout), suffix) w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filename)) if fi, err := f.Stat(); err == nil { w.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size())) } http.ServeContent(w, r, filename, time.Now(), f) }