Direct-to-S3 / Azure tus 1.0 resume IndexedDB Golden Retriever 30 locales Webcam & screen capture

Direct-to-S3 multipart upload

The browser uploads each part directly to Amazon S3 (or MinIO, Backblaze B2, Cloudflare R2, Wasabi - anything S3-API compatible) via presigned URLs your server signs on demand. Your server never sees the bytes. Survives reloads with IndexedDB resume: the resumed task reuses the existing uploadId and already-collected part ETags, so only the missing parts are re-uploaded.

What you should see: 5 MB parts uploaded straight to S3 with presigned URLs, four at a time, then completed as a multipart upload. 5 MB is S3's minimum part size for all but the final part.
Setup required. This demo needs a working S3 bucket + credentials. Edit appsettings.json:
"DemoS3": {
 "BucketName": "your-bucket",
 "Region": "us-east-1",
 "AccessKeyId": "AKIA...",
 "SecretAccessKey": "..."
}
Then restart the site. The existing DemoS3Signer implementation will auto-register with DI.

Client config

CoreUpload.create('#uploader', {
 uploadUrl: '/api/upload/upload',
 strategy: 's3', // selects _s3DirectUpload() chunkSize: 5 * 1024 * 1024, // S3 minimum 5 MB part chunkConcurrency: 4, // parallel PUTs persistState: true,
 persistAdapter: 'indexeddb' // resume survives reload
});

Server side (Program.cs)

// Register your IS3Signer (DemoS3Signer ships as reference implementation).
builder.Services.AddSingleton<IS3Signer, DemoS3Signer>();

Wire protocol

  • POST /api/upload/s3/create -> { uploadId, key }
  • POST /api/upload/s3/sign <- { uploadId, key, partNumbers } -> { urls }
  • PUT <signedUrl> -> S3 returns ETag per part
  • POST /api/upload/s3/complete <- { uploadId, key, parts:[{PartNumber, ETag}] }
  • POST /api/upload/s3/abort on cancel / fatal error

Bucket CORS

The browser PUTs directly to S3, so the bucket must allow cross-origin PUT and expose the ETag header:

[{
 "AllowedOrigins": ["https://coreupload.com"],
 "AllowedMethods": ["PUT"],
 "AllowedHeaders": ["*"],
 "ExposeHeaders": ["ETag"],
 "MaxAgeSeconds": 3000
}]