CORS error on Azure Storage calls from Javascript to commit chunked uploads

I want users to upload a huge file directly into Azure Storage. I have a Flask Python web app but I do not want the file to be uploaded into my web server due to size constraints.

When the user has selected the file they want to upload and clicks the upload button, the following happens:

  1. An API is called that generates a SAS URL and a blob name to assign to the file to be uploaded. The code that generates both is:
    blob_name = str(uuid.uuid4())  

    container_name = os.environ[default_container_name_setting]

    sas = generate_blob_sas(account_name=service.account_name,
                            account_key=access_key,
                            container_name=container_name,
                            blob_name=blob_name,
                            permission=BlobSasPermissions(write=True, read=True, create=True),
                            expiry=datetime.utcnow() + timedelta(hours=2)) 

    sas_url = 'https://' + service.account_name + '.blob.core.windows.net/' + container_name + '/' + blob_name + '?' + sas
    return sas_url, blob_name
  1. The file is then uploaded in chunks:
const chunkSize = 1024 * 1024 * 20; 
const totalChunks = Math.ceil(file.size / chunkSize);
const blockIds = []; // Array to hold block IDs

for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);
    const blockId = btoa("block-" + i); // Base64 encode block ID
    blockIds.push(blockId);

    // Upload each chunk
    const uploadResponse = await fetch(sas_url + "&comp=block&blockid=" + blockId, {
        method: "PUT",
        headers: {
            "x-ms-blob-type": "BlockBlob",
            "Content-Type": file.type
        },
        body: chunk
    });

    if (!uploadResponse.ok) {
        return false;
    }
}

It works up to this point. However, the next step is to tell Azure to put the chunks together:

const commitResponse = await fetch(sas_url + "&comp=commitBlockList", {
    method: "PUT",
    headers: {
        "Content-Type": "application/xml",
        "x-ms-version": "2020-10-02",
        "Content-Length": "0"
    },
    body: `<BlockList>${blockIds.map(id => `<Latest>${id}</Latest>`).join('')}</BlockList>`
});

if (!commitResponse.ok) {
    throw new Error("Failed to commit blocks to blob.");
}

I always get a CORS error at this point:

Access to fetch at ‘https://xxx.blob.core.windows.net/container/e07d13fa-bcd6-45cf-9eea-3295e17dc567?se=2024-11-01T04%2A18%3B30Q&sp=rcw&sv=2024-11-04&sr=b&sig=CudrFGsJ1HGnYo6Bh3K7WVAabgdOAsPteWq47XKuKDI%3D&comp=commitBlockList’ from origin ‘http://localhost:4449’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

I know I have properly set the CORS in Azure Storage because the upload part works.

Under Blob Service tab, I have added my localhost origin, with allowed methods GET, POST, OPTIONS, and PUT.

I have tried regenerating another SAS Url with the retrieved Blob name but I’m still getting the CORS error.

What am I missing?