feat: Add race upload functionality and file transfer endpoints

- Implemented IRaceUploadCommunicationClient with methods for saving races, creating race points, indexing race points, retrieving race details, and uploading files to the receiver.
- Added ReceiveFilePath option to CatalogCommunicationOptions for file transfer configuration.
- Enhanced CatalogCommunicationServiceCollectionExtensions to validate ReceiveFilePath.
- Developed RaceUploadCommunicationClient to handle race-related API interactions, including saving race data and uploading processed images.
- Updated API documentation to reflect new race upload and file transfer endpoints.
- Modified Avalonia UI to support race creation and processed image uploads, including new input fields and buttons.
- Introduced RaceSaveRequest and ReceiveFileUploadRequest models for structured data handling.
This commit is contained in:
MaddoScientisto 2026-02-28 16:54:08 +01:00
commit 15b1da4371
11 changed files with 675 additions and 97 deletions

View file

@ -178,6 +178,8 @@ Example shape:
## Race command API (`/admin/pg/Gara.abl`)
Confirmed custom commands in `GaraSvlt`:
- `asq` + `act=save` (generic save used by admin UI toolbar)
- `ni` (new record flow before save)
- `addPuntoFoto`
- `delPuntoFoto`
- `modPuntoFoto`
@ -192,12 +194,44 @@ Important parameters by command:
- `id_puntoFoto` and `id_puntoFotoIdx` for point selection
- point fields such as `descrizionePuntoFoto`, `pathRelativoFoto`, `tipoPuntoFoto`
Race save payload fields (from `admin/pg_RUS/gara.jsp` + `_V4/_js/_bean.js`):
- mandatory in practice: `descrizione`, `dataGaraInizio`, `id_tipoGara`
- commonly sent: `dataGaraFine`, `flgEventoInLinea`, `flgTipoIndex`, `pathBase`, `flgFree`, `localita`
- command envelope for save: `cmd=asq`, `act=save`
Confirmed fixed-flag value sets from UI templates:
- `flgEventoInLinea`: `0` (Non In Linea), `1` (Stand By), `2` (In Linea)
- `flgTipoIndex`: `0`, `1`
- `flgFree`: `0` (No), `1` (SI)
Server-side normalization behavior:
- `Gara.save()` appends trailing `/` to `pathBase` if missing.
- if `pathBase` is empty and `dataGaraInizio` is set, server auto-derives `pathBase` as `<year>/<id_gara>/`.
- `PuntoFoto.prepareSave()` appends trailing `/` to `pathRelativoFoto` if missing.
CSV flow coupling:
1. `cmd=saveFile` uploads to `tmp/` and returns `fileName`
2. UI stores it into hidden field `fileNameOnServer_1`
3. `cmd=salvaFileCsv` copies `DOCBASE/tmp/<fileNameOnServer_1>` to `DOCBASE/admin/csv/<id_gara>.csv`
4. `cmd=indexCsvPisa` reads `admin/csv/<id_gara>.csv` via `Gara.getImpCsvFileName()` and updates matching photos
## Processed photo transfer channel (`/ReceiveFile.abl`)
The original 3-piano -> WWW photo push does not use `Gara.abl` multipart for each processed photo.
It uses `UploadFile` against a dedicated receiver servlet:
- `POST /ReceiveFile.abl`
- servlet class: `com.ablia.servlet.ReceiveFileSvlt`
- typically unauthenticated (`isSecureServlet=false` in decompiled source)
Observed request shape:
- query params: `name`, `path`, `overwriteRemoteFile`, `bs`
- request body: raw file bytes stream
Usage in workflow:
- destination path is computed per punto-foto on remote side (`puntoFotoR.getPathCompletoFoto()`)
- processed image and thumbnail (`tn_<filename>`) are both transferred
- after transfer, photo flags are updated/indexed via DB-backed commands (`indexFoto` / CSV/indexing flows)
## Image retrieval behavior
`/foto/*` (`GetFileTnSvlt`):
@ -223,8 +257,8 @@ For robust clients, validate both:
## Practical automation sequence
1. Login on `/admin/menu/Menu4.abl` with `cmdIU=check`, store cookies.
2. Create/update race data on `/admin/pg/Gara.abl` with regular form commands.
3. Upload images with `cmd=loadImg`.
4. (Optional) upload CSV with `cmd=saveFile`.
5. Finalize CSV placement with `cmd=salvaFileCsv` and run `cmd=indexCsvPisa`.
2. Create race on `/admin/pg_RUS/Gara.abl` with `cmd=asq`, `act=save` and race fields.
3. Create and/or manage punti foto (`addPuntoFoto`, `creaPuntiFoto`, `modPuntoFoto`).
4. Transfer processed files with `/ReceiveFile.abl` to remote race/punto paths.
5. Trigger indexing (`indexFoto` per punto, or CSV via `saveFile` + `salvaFileCsv` + `indexCsvPisa`).
6. Read thumbnails from `/foto/*` and originals from `/fotoOriginali/*`.