Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure download blob filestream/memorystream

I want users to be able to download blobs from my website. I want the fastest/cheapeast/best way to do this.

Heres what i came up with:

        CloudBlobContainer blobContainer = CloudStorageServices.GetCloudBlobsContainer();

        CloudBlockBlob blob = blobContainer.GetBlockBlobReference(blobName);
        MemoryStream memStream = new MemoryStream();
        blob.DownloadToStream(memStream);

        Response.ContentType = blob.Properties.ContentType;
        Response.AddHeader("Content-Disposition", "Attachment; filename=" + fileName + fileExtension);
        Response.AddHeader("Content-Length", (blob.Properties.Length).ToString());
        Response.BinaryWrite(memStream.ToArray());
        Response.End();

I'm using memorystream now but im guessing i should go with filestream because off the blobs being, in some cases, large.. Right?

I tried it with filestream but I failed miserable.. Think you could give me some code for filestream?

like image 700
Reft Avatar asked May 22 '14 12:05

Reft


2 Answers

IMHO, the cheapest and fastest solution would be directly downloading from blob storage. Currently your code is first downloading the blob on your server and streaming from there. What you could do instead is create a Shared Access Signature with Read permission and Content-Disposition header set and create blob URL based on that and use that URL. In this case, the blob contents will be directly streamed from storage to the client browser.

For example look at the code below:

    public ActionResult Download()
    {
        CloudStorageAccount account = new CloudStorageAccount(new StorageCredentials("accountname", "accountkey"), true);
        var blobClient = account.CreateCloudBlobClient();
        var container = blobClient.GetContainerReference("container-name");
        var blob = container.GetBlockBlobReference("file-name");
        var sasToken = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
            {
                Permissions = SharedAccessBlobPermissions.Read,
                SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10),//assuming the blob can be downloaded in 10 miinutes
            }, new SharedAccessBlobHeaders()
            {
                ContentDisposition = "attachment; filename=file-name"
            });
        var blobUrl = string.Format("{0}{1}", blob.Uri, sasToken);
        return Redirect(blobUrl);
    }
like image 157
Gaurav Mantri Avatar answered Oct 03 '22 01:10

Gaurav Mantri


Your code is almost right. Try this:

    public virtual ActionResult DownloadFile(string name)
    {
        Response.AddHeader("Content-Disposition", "attachment; filename=" + name); // force download
        CloudBlobContainer blobContainer = CloudStorageServices.GetCloudBlobsContainer();
    CloudBlockBlob blob = blobContainer.GetBlockBlobReference(blobName);
        blob.DownloadToStream(Response.OutputStream);
        return new EmptyResult();
    }

Hope this helps.

like image 23
lopezbertoni Avatar answered Oct 03 '22 01:10

lopezbertoni