feat: base go mkiso
This commit is contained in:
133
internal/handler/iso.go
Normal file
133
internal/handler/iso.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"mkiso-server/internal/service"
|
||||
)
|
||||
|
||||
// writeJSON is a helper to write a JSON response.
|
||||
func writeJSON(w http.ResponseWriter, status int, v interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
json.NewEncoder(w).Encode(v)
|
||||
}
|
||||
|
||||
// DownloadSingle handles GET /api/iso/download?accession_number=X
|
||||
// Returns an ISO file as application/octet-stream.
|
||||
func DownloadSingle(isoSvc *service.ISOService) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
acc := r.URL.Query().Get("accession_number")
|
||||
if acc == "" {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "missing accession_number"})
|
||||
return
|
||||
}
|
||||
acc = strings.TrimSpace(acc)
|
||||
|
||||
slog.Info("handling download single", "accession", acc)
|
||||
|
||||
item, err := isoSvc.GenerateISO(r.Context(), acc)
|
||||
if err != nil {
|
||||
slog.Error("ISO generation failed", "accession", acc, "error", err)
|
||||
status := http.StatusInternalServerError
|
||||
msg := "ISO creation failed"
|
||||
if strings.Contains(err.Error(), "no DICOM data") {
|
||||
status = http.StatusNotFound
|
||||
msg = "no DICOM data for accession_number"
|
||||
}
|
||||
writeJSON(w, status, map[string]string{
|
||||
"error": msg,
|
||||
"detail": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
defer item.Cleanup()
|
||||
|
||||
// Stream ISO file
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, item.Filename))
|
||||
|
||||
data, err := os.ReadFile(item.Path)
|
||||
if err != nil {
|
||||
slog.Error("read ISO file failed", "path", item.Path, "error", err)
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to read ISO"})
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(data)
|
||||
slog.Info("ISO download completed", "accession", acc, "size", len(data))
|
||||
}
|
||||
}
|
||||
|
||||
// DownloadMultiple handles GET /api/iso/download-multiple?accession_numbers=X,Y,Z
|
||||
// Returns an ISO file as application/octet-stream.
|
||||
func DownloadMultiple(isoSvc *service.ISOService) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
raw := r.URL.Query().Get("accession_numbers")
|
||||
if raw == "" {
|
||||
// Also check for "accession_number" with comma (backward compat)
|
||||
raw = r.URL.Query().Get("accession_number")
|
||||
}
|
||||
if raw == "" {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "missing accession_numbers"})
|
||||
return
|
||||
}
|
||||
|
||||
accs := parseAccessions(raw)
|
||||
if len(accs) == 0 {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "empty accession_number list"})
|
||||
return
|
||||
}
|
||||
|
||||
slog.Info("handling download multiple", "accessions", accs)
|
||||
|
||||
item, err := isoSvc.GenerateISOMultiple(r.Context(), accs)
|
||||
if err != nil {
|
||||
slog.Error("ISO generation failed", "accessions", accs, "error", err)
|
||||
status := http.StatusInternalServerError
|
||||
msg := "ISO creation failed"
|
||||
if strings.Contains(err.Error(), "no DICOM data") {
|
||||
status = http.StatusNotFound
|
||||
msg = "no DICOM data for accession_numbers"
|
||||
}
|
||||
writeJSON(w, status, map[string]string{
|
||||
"error": msg,
|
||||
"detail": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
defer item.Cleanup()
|
||||
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, item.Filename))
|
||||
|
||||
data, err := os.ReadFile(item.Path)
|
||||
if err != nil {
|
||||
slog.Error("read ISO file failed", "path", item.Path, "error", err)
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to read ISO"})
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(data)
|
||||
slog.Info("ISO download completed (multiple)", "accessions", accs, "size", len(data))
|
||||
}
|
||||
}
|
||||
|
||||
// parseAccessions parses a comma-separated list of accession numbers,
|
||||
// trimming whitespace and filtering empty entries.
|
||||
func parseAccessions(raw string) []string {
|
||||
parts := strings.Split(raw, ",")
|
||||
var result []string
|
||||
for _, p := range parts {
|
||||
p = strings.TrimSpace(p)
|
||||
if p != "" {
|
||||
result = append(result, p)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user