Upload Process
In this guide you will learn:
- The two upload paths: direct SAS upload and blob-to-blob copy
- How upload sessions, commits, and ingestion work
- How the sync engine handles interruptions and retries
Overview
Section titled “Overview”When you click Sync on a manifest, the desktop app uploads each approved encounter and its images to the finwave server. The exact upload mechanism depends on where your images are stored.
Local images: SAS URI upload
Section titled “Local images: SAS URI upload”For images stored on local disk (or external drives), the upload flow is:
- Create upload sessions — The desktop sends a batch request to the server with file names and sizes. The server returns a pre-signed SAS URI for each file, pointing to a temporary blob in the encounter’s storage container.
- Upload to blob storage — The desktop uploads each image directly to Azure Blob Storage using the SAS URI. This is a PUT request with the image bytes. Large files get a scaled timeout (60s base + ~10s per MB).
- Commit — After all images in a batch are uploaded, the desktop sends a commit request. The server verifies the blobs, creates FileItem records, generates resize variants (thumbnails, previews), and triggers the ML pipeline.
Each upload has an idempotency key (based on the encounter ID and scan ID). If you re-sync, the server recognizes already-uploaded images and returns Complete without re-uploading.
Azure images: blob-to-blob copy
Section titled “Azure images: blob-to-blob copy”For images stored in Azure Blob Storage (discovered via cloud scanning), a faster path is used:
- Generate read SAS — The desktop generates a short-lived read-only SAS URL for each source blob using your stored Azure credentials.
- Server-side copy — The desktop sends these SAS URLs to the finwave server, which copies blobs directly between storage accounts using
SyncCopyFromUri. No image data passes through the desktop. - Commit and ingest — Same as local uploads: the server creates FileItems, resizes, and triggers ML.
This is significantly faster for large datasets since images move between Azure data centers without touching your local network.
Retry and resumability
Section titled “Retry and resumability”The sync engine is designed to handle interruptions gracefully:
- Transient errors (5xx) — Upload sessions, commits, and blob copies retry up to 3 times with exponential backoff (2s, 4s delays).
- Interrupted sync — If you close the app mid-sync, the encounter’s remote ID is saved locally. On the next sync, the engine skips encounter creation and resumes image upload.
- Partial success — If some images in an encounter fail, the encounter is marked “partial.” Click Retry to re-upload only the failed images. Already-uploaded images are not duplicated.
- SAS URI expiry — If a SAS URI expires during upload (403 with “Signature not valid”), the engine refreshes the URI automatically.
Upload session lifecycle
Section titled “Upload session lifecycle”Each image goes through these statuses:
| Status | Meaning |
|---|---|
| Pending | Upload session created, SAS URI issued |
| Uploading | Bytes being sent to blob storage |
| Committed | Upload confirmed, blob verified |
| Complete | Ingestion done: FileItem created, resized, ML triggered |
| Error | Upload or ingestion failed (see error detail) |
Related
Section titled “Related”- How Sync Works — The full sync pipeline overview
- Azure Blob Storage — Setting up cloud storage connections
- Sync Troubleshooting — Fixing common upload errors
- Sync Configuration — Concurrency and API key settings