PeteShack
PeteShack

Reputation: 707

best way to download large files from azure cloud storage

I have an MVC web app running in azure that serves up large files like mp3's, pdf's, etc... that are stored in cloud storage. What's the best way to serve those files, so users can download them when clicking on a link/button?

The easy way is just to show them with:

<a href="...blob.core.windows.net/container/file.mp3">

But then the user has to right-click to download.

To force a download, you can return a File ActionResult:

public ActionResult GetPDF( string filename )
{
    return File( filename, "application/pdf", Server.HtmlEncode( filename ) );
}

The drawback with this ( I think ) is that the webrole has to read in the files and output them to the stream, which would consume resources, and potentially bog down the role with lots of users. Whereas the simple href link solution basically hands off the work so the browser talks directly to cloud storage.

Am I correct? Should I be concerned about the extra work on the webrole?

Is there another way to force a file download without burdening the webrole?

UPDATE:

So what I ended up doing was uploading the mp3's with Content-Type "binary/octet-stream" - this seems to force a download prompt. Not sure if it's a good practice, but it works so far.

Upvotes: 5

Views: 5804

Answers (3)

Sadia Saqib
Sadia Saqib

Reputation: 11

You can return the outputFileName which contain the path where file is downloading and display that path at front end with message that file has been downloaded at location [...]

Upvotes: 1

Habib Ben Radhouene
Habib Ben Radhouene

Reputation: 11

I have developped an ActionResult tha get the file from the storage but i didn't arrice to output it to the stream and return a downloaded file , can i get a help please this my action code : public ActionResult GetPDF( string filename ) {

    var storageAccountName = this.User.StorageAccountName;
        var storageAccountKey = this.User.StorageAccountKey;
        string connectionString = string.Format(
                    "DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                     storageAccountName, storageAccountKey);

        //Extraction de votre chaîne de connexion par programme
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);

        //Create a CloudFileClient object for credentialed access to File storage.
        CloudFileClient fileClient = storageAccount.CreateCloudFileClient();

        //Get a reference to the file share . create a share folder take the name of CompanyCode
        CloudFileShare share = fileClient.GetShareReference(this.User.CompanyCode);

        share.CreateIfNotExists();
        byte[] fileBytes = null;
        // create if not Exist
        if (share.Exists())
        {
            // string StoragePath = "/Uploads/Locations/" + LocationToAdd.Id.ToString();

            CloudFileDirectory rootDirectory = share.GetRootDirectoryReference();
            CloudFileDirectory topDirectory = rootDirectory.GetDirectoryReference("Uploads");
            topDirectory.CreateIfNotExistsAsync();
            CloudFileDirectory midDirectory = topDirectory.GetDirectoryReference("Locations");
            midDirectory.CreateIfNotExistsAsync();
            CloudFileDirectory sampleDir = midDirectory.GetDirectoryReference(document1.LocationId.ToString());
            sampleDir.CreateIfNotExistsAsync();
            //Get a reference to the file we created previously.
            CloudFile file = sampleDir.GetFileReference(filename);

            if (file.Exists())
            {
                //Write the contents of the file to the console window.
                // string fileresult = file.DownloadTextAsync().Result;
                //  file.DownloadToByteArray(fileBytes, 1, null, null, null);

                string outputFileName = Path.GetTempFileName();
                if (System.IO.File.Exists(outputFileName))
                {
                    System.IO.File.Delete(outputFileName);
                }
                OperationContext context = new OperationContext();
                file.DownloadToFileAsync(outputFileName, FileMode.CreateNew, null, null, context);

                // what should i do after this ........
            }
            }
            }
}

Upvotes: 0

knightpfhor
knightpfhor

Reputation: 9409

Your assumption is correct, if you want to use the ActionResult you would need to download the file to the web role first and then stream it down to the client. If you can you want to avoid this particularly with large files and leave it up to Azure Storage because then Microsoft has to worry about dealing with the request, you don't have to pay for more web roles if you get lots of traffic.

This works well if all of the files you're hosting are public, but gets a little trickier if you want to secure the files (look into shared access signatures if that it what you want to do).

Have you tried setting the content type on the blob? Depending on how you've uploaded the files to blob storage they may not be set. If you're uploading the blobs through your own code you can access this through CloudBlob.Attributes.Properties.ContentType (from MSDN)

Upvotes: 4

Related Questions