Ole Albers
Ole Albers

Reputation: 9305

404 for a small period of time after uploading file to Azure Blob Storage

I upload attachments to an Azure Blob storage. I also create a SAS-Token when uploading; I retrieve the unique URL, send it to the browser where it is opened immediatly.

When I do this I often (but not always) retrieve a 404 that this resource does not exist. When refreshing the page just a few seconds later it is retrieved correctly.

So it seems that I am "too fast" after uploading the attachment. Is there a way to wait until Azure is ready to serve the attachment? I would have expected awaiting the call would be sufficient to achieve this.

public async void UploadFile(string filename, byte[] filecontent)
{
    var containerClient = _blobServiceclient.GetBlobContainerClient("attachments");
    var blobClient = containerClient.GetBlobClient(filename);
    
    using (var stream = new MemoryStream(filecontent))
    {
      await blobClient.UploadAsync(stream, new BlobHttpHeaders { ContentType = GetContentTypeByFilename(filename) });
    }
}


  public async Task<string> GetLinkForFile(string filename)
{
    var containerClient = _blobServiceclient.GetBlobContainerClient("attachments");
    
    var sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = containerName,
        BlobName = filename,
        Resource = "b",
        StartsOn = DateTime.UtcNow.AddMinutes(-1),
        ExpiresOn = DateTime.UtcNow.AddMinutes(5),
    };

    // Specify read permissions
    sasBuilder.SetPermissions(BlobSasPermissions.Read);

    var credentials = new StorageSharedKeyCredential(_blobServiceclient.AccountName, _accountKey);
    var sasToken = sasBuilder.ToSasQueryParameters(credentials);

    // Construct the full URI, including the SAS token.
    UriBuilder fullUri = new UriBuilder()
    {
        Scheme = "https",
        Host = string.Format("{0}.blob.core.windows.net", _blobServiceclient.AccountName),
        Path = string.Format("{0}/{1}", containerName, filename),
        Query = sasToken.ToString()
    };

    return fullUri.ToString();
}



public async Task<Document> GetInvoice(byte[] invoiceContent, string invoiceFilename)
{
    string filePath = await GetLinkForFile(invoiceFilename);
    UploadFile(invoiceFilename, file);
    
    return new Document()
    {           
        Url = filePath
    };  
}

The method GetInvoice is called by REST and the response (containing the URL) returned to the browser where it is opened.

Upvotes: 2

Views: 602

Answers (1)

Gaurav Mantri
Gaurav Mantri

Reputation: 136306

If you notice, you're not waiting for the upload operation to finish here:

_azureStorageRepository.UploadFile(invoiceFilename, file);

Please change this to:

await _azureStorageRepository.UploadFile(invoiceFilename, file);

And you should not see the 404 error. Azure Blob Storage is strongly consistent.

Also, change the UploadFile method from public async void UploadFile to public async Task UploadFile as mentioned by @Fildor in the comments.

Upvotes: 3

Related Questions