Direct-to-Azure Blob

Browser-direct Azure Blob upload

The browser uploads each block via PutBlock against a pre-signed blob SAS URL, then finalises with a single PutBlockList. Mirrors the S3 pattern — your server signs once and the bytes bypass IIS entirely. IndexedDB resume preserves the upload session + already-committed block IDs so reloads pick up where they stopped.

Client config
AjaxUploader.create('#uploader', {
    uploadUrl: '/ajaxupload.axd/upload',
    strategy: 'azure',
    chunkSize: 4 * 1024 * 1024,     // Azure block size
    chunkConcurrency: 4,
    persistState: true,
    persistAdapter: 'indexeddb'
});
Server-side (Global.asax.cs)
using AjaxUploader.Providers;

protected void Application_Start(object sender, EventArgs e)
{
    // Your IAzureSigner wraps BlobServiceClient and hands out SAS URLs.
    Azure.Signer = new MyAzureSigner(
        connectionString: ConfigurationManager.ConnectionStrings["AzureStorage"].ConnectionString,
        containerName: "uploads");
}
Wire protocol
  • POST /ajaxupload.axd/azure/create → { uploadId, blobUrl, blockIdPrefix }
  • PUT {blobUrl}&comp=block&blockid=... per block (browser-direct)
  • PUT {blobUrl}&comp=blocklist with XML BlockList body (browser-direct)
  • POST /ajaxupload.axd/azure/complete to record metadata server-side
Container CORS
az storage cors add \
  --methods PUT \
  --origins https://ajaxuploader.com \
  --allowed-headers "*" \
  --exposed-headers "*" \
  --services b \
  --max-age 3600