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 returnsETagper partPOST /api/upload/s3/complete<-{ uploadId, key, parts:[{PartNumber, ETag}] }POST /api/upload/s3/aborton 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
}]