Skip to content

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

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.

For images stored on local disk (or external drives), the upload flow is:

  1. 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.
  2. 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).
  3. 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.

For images stored in Azure Blob Storage (discovered via cloud scanning), a faster path is used:

  1. Generate read SAS — The desktop generates a short-lived read-only SAS URL for each source blob using your stored Azure credentials.
  2. 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.
  3. 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.

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.

Each image goes through these statuses:

StatusMeaning
PendingUpload session created, SAS URI issued
UploadingBytes being sent to blob storage
CommittedUpload confirmed, blob verified
CompleteIngestion done: FileItem created, resized, ML triggered
ErrorUpload or ingestion failed (see error detail)