package files import ( "fmt" "gis/app" "gis/server/httputil" "net/http" "path/filepath" "strings" "time" "github.com/minio/minio-go/v7" ) func uploadFileRoute(application *app.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if err := r.ParseMultipartForm(64 << 20); err != nil { httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "request too large or not multipart"}) return } rawFileType := r.FormValue("file_type") if rawFileType == "" { httputil.WriteJSON(w, http.StatusUnprocessableEntity, map[string]string{"error": "file_type is required"}) return } ft := FileType(rawFileType) if ft != FileTypeVectorWithTable && ft != FileTypeVector && ft != FileTypeRaster { httputil.WriteJSON(w, http.StatusUnprocessableEntity, map[string]string{"error": "invalid file_type"}) return } f, header, err := r.FormFile("file") if err != nil { httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "file is required"}) return } defer f.Close() ext := strings.ToLower(filepath.Ext(header.Filename)) if ext == "" { httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "unsupported file format"}) return } if _, ok := allowedExtensions[ext]; !ok { httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "unsupported file format"}) return } storageKey := fmt.Sprintf("%d_%s", time.Now().UnixNano(), header.Filename) _, err = application.S3.PutObject( r.Context(), application.Cfg.S3Bucket, storageKey, f, header.Size, minio.PutObjectOptions{ContentType: header.Header.Get("Content-Type")}, ) if err != nil { httputil.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to store file"}) return } var gf GeoFile err = application.Db.QueryRow(r.Context(), `INSERT INTO files (filename, storage_key, file_type) VALUES ($1, $2, $3) RETURNING id, filename, file_type, validation_status, validation_error, kato_column, crs, feature_count, uploaded_at, updated_at`, header.Filename, storageKey, ft, ).Scan( &gf.ID, &gf.Filename, &gf.FileType, &gf.ValidationStatus, &gf.ValidationError, &gf.KatoColumn, &gf.CRS, &gf.FeatureCount, &gf.UploadedAt, &gf.UpdatedAt, ) if err != nil { httputil.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to save file record"}) return } httputil.WriteJSON(w, http.StatusAccepted, gf) } }