I am creating a website using Azure Blobs to store content. The website provides Search and Indexing.
When this link is relative,
<a download="" href="./media5/yyy.png">Download</a>
the browser kicks off a "download".
When the files are stored in Blobs, the users get a link like:
<a download="" href="https://xxx.blob.core.windows.net/media5/yyy.png">Download</a>
However, this navigates to the image.
I need the browser "download" to work.
I have tries setting the Storage Account's CORS Blade:
But this did not do anything.
CodePudding user response:
CORS is not going to help in this case. If you want to force download the blob, please change the blob's content-type property to application/octet-stream
(or application/binary
).
However, please note that when you change the blob's content type to application/octet-stream
, it will always be downloaded. You will not be able to display the blob in the browser.
CodePudding user response:
Manrti is correct CORS is not in play. I deleted the Storage Account's CORS Blade.
The fix is 3 parts: 1: Set ContentDispoistion header to "attached"
var blockBlobClient = new BlockBlobClient(connectionString, container, fileInfo.Name, clientOptions);
var uploadOptions = new BlobUploadOptions();
uploadOptions.HttpHeaders = new BlobHttpHeaders();
switch (fileInfo.Extension)
{
case ".wav":
uploadOptions.HttpHeaders.ContentType = "audio/wav";
break;
case ".mp3":
uploadOptions.HttpHeaders.ContentType = "audio/mpeg";
break;
case ".mp4":
uploadOptions.HttpHeaders.ContentType = "video/mp4";
break;
case ".jpg":
uploadOptions.HttpHeaders.ContentType = "image/jpeg";
break;
case ".png":
uploadOptions.HttpHeaders.ContentType = "image/png";
break;
case ".zip":
uploadOptions.HttpHeaders.ContentType = "application/x-zip-compressed";
break;
case ".html":
uploadOptions.HttpHeaders.ContentType = "text/plain";
break;
case ".pdf":
uploadOptions.HttpHeaders.ContentType = "application/pdf";
break;
default:
break;
}
uploadOptions.HttpHeaders.ContentDisposition = "attached";
uploadOptions.ProgressHandler = progressHandler;
var contentMD5 = await GetContentMD5(blockBlobClient);
var contentType = await GetContentType(blockBlobClient);
using (var fs = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
{
if ((sourceMD5 != contentMD5) | (contentType != uploadOptions.HttpHeaders.ContentType))
{
Console.WriteLine("\t\tUploading Blob...");
await blockBlobClient.UploadAsync(fs, uploadOptions);
contentMD5 = await GetContentMD5(blockBlobClient);
if (sourceMD5 != contentMD5)
{
throw new Exception($"Uploaded blob ContentMD5[{contentMD5}] does not match SourceMD5Hash[{sourceMD5}] for {blockBlobClient.Name}");
}
}
return blockBlobClient;
}
2: You must use a SAS Url to have the Content-Disposition header be returned:
var uri = blobClient.GenerateSasUri(BlobSasPermissions.Read, new DateTimeOffset(DateTime.UtcNow.AddYears(2)));
3: HTML Link:
<a download="" href="https://xxx.blob.core.windows.net/media5/yyy.png?sv=2020-08-04&se=2024-04-08T14:43:28Z&sr=b&sp=r&sig=ZWdbpd8y2hr02MpzgxDC/u2eqi5HukIYhXnLiYK4Rrk=">Download</a>