0
votes

I can successfully upload to Azure Blob Storage, but I'm having issues downloading files (csv and pdf files).

My goal is for the file to download to the browser (since this will be a web app and I will not know the local path to download the file to).

        string connString = ConfigurationManager.ConnectionStrings["MyTestStorageAccount"].ConnectionString;
        CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(connString);
        CloudBlobClient _blobClient = cloudStorageAccount.CreateCloudBlobClient();
        CloudBlobContainer _cloudBlobContainer = _blobClient.GetContainerReference("filestorage");
        CloudBlockBlob _blockBlob = _cloudBlobContainer.GetBlockBlobReference("testfile.csv");
        Response.AddHeader("Content-Disposition", "attachment; filename=" + "testfile.csv");
        _blockBlob.DownloadToStream(Response.OutputStream);
2
Please edit to include the behavior you're seeing: errors, etc. As written, we cannot see the types of issues you're having.David Makogon
Is your blob set to a private access policy?trejas

2 Answers

0
votes

I follow your code in mvc and download csv in my site, when I open it, the content inside is not what I added but some html template.

If this is your problem, you could refer to the following code:

public ActionResult Download()
    {
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));

            CloudBlobClient _blobClient = cloudStorageAccount.CreateCloudBlobClient();
            CloudBlobContainer _cloudBlobContainer = _blobClient.GetContainerReference("data");
            CloudBlockBlob _blockBlob = _cloudBlobContainer.GetBlockBlobReference("table.csv");
            Response.AddHeader("Content-Disposition", "attachment; filename=" + "table.csv");
             MemoryStream ms = new MemoryStream();
            _blockBlob.DownloadToStream(ms);
            ms.Position = 0;
            return File(ms, "application/octet-stream", "table.csv");
}

Also you could return Redirect(blobUrl);

BTW, if your blob is private, you need to 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 more details, refer to the following code:

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);
    }
0
votes

I have tested your code, it worked fine. You can tell us your problem like error message, more detailed requirements,etc.

I create a generic handler(ashx) to test it and here is my tested code for your reference:

<%@ WebHandler Language="C#" Class="DownloadHandler" %>

using System.Web;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

public class DownloadHandler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {


        CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=your_account;AccountKey=your_key;EndpointSuffix=core.windows.net");

        CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();

        CloudBlobContainer container = cloudBlobClient.GetContainerReference("mycontainer");
        container.CreateIfNotExists();

        CloudBlockBlob blob = container.GetBlockBlobReference("4.PNG");
        context.Response.AddHeader("Content-Disposition", "attachment; filename=" + "4.PNG");
        blob.DownloadToStream(context.Response.OutputStream);

    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

Screenshot of result:

When i access this handler via IE 11

enter image description here