Add CSV file upload and auto-delimiter detection for pilot import

Allows uploading a CSV file directly instead of only pasting text, and
auto-detects comma vs semicolon separators to support more locales.
This commit is contained in:
Jan Meinl
2026-08-19 15:32:26 +02:00
parent 4b5f0eb326
commit 65bb2b351f
10 changed files with 97 additions and 16 deletions
+38 -5
View File
@@ -164,6 +164,18 @@ func handleDeletePilot(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}
// detectSeparator counts commas vs semicolons in the first line to pick the delimiter.
func detectSeparator(data []byte) rune {
sample := string(data)
if idx := strings.IndexByte(sample, '\n'); idx > 0 {
sample = sample[:idx]
}
if strings.Count(sample, ";") > strings.Count(sample, ",") {
return ';'
}
return ','
}
func handleImportPilots(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
if err != nil {
@@ -174,13 +186,34 @@ func handleImportPilots(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusForbidden, "forbidden")
return
}
// Cap the upload to keep memory bounded.
body, err := io.ReadAll(io.LimitReader(r.Body, 2*1024*1024))
if err != nil {
writeError(w, http.StatusBadRequest, "read_error")
return
var body []byte
if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/form-data") {
if err := r.ParseMultipartForm(2 * 1024 * 1024); err != nil {
writeError(w, http.StatusBadRequest, "read_error")
return
}
f, _, err := r.FormFile("file")
if err != nil {
writeError(w, http.StatusBadRequest, "missing_file")
return
}
defer f.Close()
body, err = io.ReadAll(io.LimitReader(f, 2*1024*1024))
if err != nil {
writeError(w, http.StatusBadRequest, "read_error")
return
}
} else {
body, err = io.ReadAll(io.LimitReader(r.Body, 2*1024*1024))
if err != nil {
writeError(w, http.StatusBadRequest, "read_error")
return
}
}
reader := csv.NewReader(strings.NewReader(string(body)))
reader.Comma = detectSeparator(body)
reader.FieldsPerRecord = -1
records, err := reader.ReadAll()
if err != nil {