Reputation: 33
I've been using azure storage blob for some time without issue in an asp.net mvc site. Recently, I have begun to have issues with corrupted files after downloading. If I download straight from azure, the file is still valid. I've only been able to find some notes related to an issue with async downloading from azure. Keep in mind, this issue only seems to be related to some files??
Here was my old download method.
public async Task<ActionResult> Download(int id)
{
var file = await db.O_File.SingleAsync(x => x.Id == id);
var data = await _storage.Download(file.FileName);
return File(data, "application/octet-stream", file.DisplayFileName);
}
This is my new non-async version, however I'm getting an error on the final line - cannot convert from 'system.threading.tasks.task' to 'string'.
public ActionResult Download(int id)
{
var file = db.O_File.Single(x => x.Id == id);
var data = _storage.Download(file.FileName);
return File(data, "application/octet-stream", file.DisplayFileName);
}
Am I missing something here - why can't I just remove async options here. Additionally, am I missing something else entirely as to why the files are downloading corrupt?
Upvotes: 1
Views: 2443
Reputation: 8491
If you want to provide a way of downloading file from Azure Storage. You could generate a file link with SAS key and let client side downloading this file directly from Azure Storage. It will reduce the workload of your web server and increase the response speed. Here is the code of generating blob URL with SAS token.
public string GetBlobSasUri(string containerName, string blobName, string connectionstring)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionstring);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(containerName);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
//Set the expiry time and permissions for the blob.
//In this case no start time is specified, so the shared access signature becomes valid immediately.
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;
//Generate the shared access signature on the blob, setting the constraints directly on the signature.
string sasContainerToken = blockBlob.GetSharedAccessSignature(sasConstraints);
//Return the URI string for the blob, including the SAS token.
return blockBlob.Uri + sasContainerToken;
}
In your web application, you just need to redirect to the URL which obtained in earlier step.
public ActionResult Download()
{
string blobURL = GetBlobSasUri("blob name","container name", "connection string");
return Redirect(blobURL);
}
Upvotes: 0
Reputation: 5977
On your non-async version, you might get that error if you _storage.Download method still uses an async method in it (such as Block Blob DownloadToStreamAsync)
If your download method is grabbing the blob as a stream, make sure you reset the stream before sending it to the browser:
data.Seek(0, SeekOrigin.Begin);
Upvotes: 1