使用ASP.NET和MVC5下载LandRogeToStreamAsync和文件保存

时间:2014-11-26 11:51:32

标签: c# asp.net-mvc azure asp.net-mvc-5 azure-storage

我正在尝试以CloudBlockBlob的形式从Azure存储下载文件。我想允许用户选择下载文件的放置位置,因此我编写了以下代码来执行此操作

[AllowAnonymous]
public async Task<ActionResult> DownloadFile(string displayName)
{
    ApplicationUser user = null;
    if (ModelState.IsValid)
    {
        user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

        // Retrieve storage account and blob client.
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
            ConfigurationManager.AppSettings["StorageConnectionString"]);
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference(
            VisasysNET.Utilities.Constants.ContainerName);

        // If the container does not exist, return error.
        if (container.Exists())
        {
            foreach (IListBlobItem item in container.ListBlobs(null, false))
            {
                if (item.GetType() == typeof(CloudBlockBlob))
                {
                    CloudBlockBlob blob = (CloudBlockBlob)item;
                    if (blob.Name.CompareNoCase(displayName))
                    {
                        using (Stream stream = new MemoryStream())
                        {
                            await blob.DownloadRangeToStreamAsync(stream, null, null);
                            return File(stream, displayName);
                        }
                    }
                }
            }
            return RedirectToAction("Index", "Tools");
        }
    }
    return new HttpStatusCodeResult(HttpStatusCode.ServiceUnavailable);
}

这个想法是返回FileStreamResult并允许浏览器提供“保存对话框”。但是,当控制器发布到视图时,我得到了

  

无法访问已关闭的Stream。   异常详细信息:System.ObjectDisposedException:无法访问已关闭的Stream。

现在问题很明显,然而,如何规避它不是。我想确保MemoryStream被释放和处理,因为它可能容纳数据高达~10M。 如何处置MemoryStream但允许FileStreamResult传回并由浏览器使用?

感谢您的时间。

1 个答案:

答案 0 :(得分:1)

只是不要处理它。请查看FileStreamResult implementation

 protected override void WriteFile(HttpResponseBase response) {
            // grab chunks of data and write to the output stream
            Stream outputStream = response.OutputStream;
            using (FileStream) {
                byte[] buffer = new byte[_bufferSize];

                while (true) {
                    int bytesRead = FileStream.Read(buffer, 0, _bufferSize);
                    if (bytesRead == 0) {
                        // no more data
                        break;
                    }

                    outputStream.Write(buffer, 0, bytesRead);
                }
            }
        }

FileStreamResult将您的流写入response.OutputStream;

后将其处理掉

如果您不必通过网站(安全性)代理下载,则可以生成共享访问签名并将用户直接重定向到存储。 See here