package handlers import ( "archive/zip" "bytes" "encoding/json" "fmt" "io" "net/http" "github.com/gabriel-vasile/mimetype" "github.com/valkey-io/valkey-go" ) func DownloadFile(client valkey.Client) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { upload_id := r.PathValue("upload_id") if upload_id == "" { w.WriteHeader(http.StatusBadRequest) return } file_id := r.PathValue("file_id") if file_id == "" { w.WriteHeader(http.StatusBadRequest) return } files_json, err := client.Do(r.Context(), client.B().Get().Key(upload_id).Build()).ToString() if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } var files []string err = json.Unmarshal([]byte(files_json), &files) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } found := false found_id := 0 for i, id := range files { if id == file_id { found = true found_id = i } } if !found { http.Error(w, "not found", http.StatusNotFound) return } file := files[found_id] filename, err := client.Do(r.Context(), client.B().Get().Key(file+":filename").Build()).ToString() if err != nil { return } fileContents, err := client.Do(r.Context(), client.B().Get().Key(file+":contents").Build()).AsBytes() if err != nil { return } w.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename)) mime := mimetype.Detect(fileContents) w.Header().Add("mimetype", mime.String()) w.Write(fileContents) } } func DownloadFilesZipped(client valkey.Client) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { upload_id := r.PathValue("upload_id") if upload_id == "" { w.WriteHeader(http.StatusBadRequest) return } files_json, err := client.Do(r.Context(), client.B().Get().Key(upload_id).Build()).ToString() if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } var files []string err = json.Unmarshal([]byte(files_json), &files) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if len(files) == 1 { file := files[0] filename, err := client.Do(r.Context(), client.B().Get().Key(file+":filename").Build()).ToString() if err != nil { return } fileContents, err := client.Do(r.Context(), client.B().Get().Key(file+":contents").Build()).AsBytes() if err != nil { return } w.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename)) mime := mimetype.Detect(fileContents) w.Header().Add("mimetype", mime.String()) w.Write(fileContents) return } zipBuf := new(bytes.Buffer) zipWriter := zip.NewWriter(zipBuf) for _, file := range files { filename, err := client.Do(r.Context(), client.B().Get().Key(file+":filename").Build()).ToString() if err != nil { continue } fileContents, err := client.Do(r.Context(), client.B().Get().Key(file+":contents").Build()).AsBytes() if err != nil { continue } w, err := zipWriter.Create(filename) if err != nil { continue } w.Write(fileContents) } zipWriter.Close() w.Header().Add("mimetype", "application/zip") w.Header().Add("Content-Disposition", `attachment; filename="timeshare-download.zip"`) io.Copy(w, zipBuf) } }