Azure Blob存储:DownloadToByteArray VS DownloadToStream

Jul*_*len 35 c# azure

我一直在使用Azure Blob存储服务来保存/恢复要在Azure网页中托管的网页上下文中的文件.

在学习过程中,我提出了两个解决方案; 第一个基本上使用DownloadToStream哪个相同,但有一个FileStream.在这种情况下,我必须在将文件返回给用户之前将其写入服务器.

public static Stream GetFileContent(string fileName, HttpContextBase context)
{
      CloudBlobContainer container = GetBlobContainer();    
      CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);                                       
      Stream fileStream = new FileStream(
          context.Server.MapPath("~/App_Data/files/" + fileName), FileMode.Create);   
      blockBlob.DownloadToStream(fileStream);
      fileStream.Close();    
      return File.OpenRead(context.Server.MapPath("~/App_Data/files/" + fileName));
}

public ActionResult Download(string fileName)
{
    byte[] fileContent = MyFileContext.GetFileContent(fileName);
    return File(fileContent, "application/zip", fileName);        
}
Run Code Online (Sandbox Code Playgroud)

另一方面,我使用DownloadToByteArray函数将Blob的内容写入用Blob文件的大小初始化的字节数组中.

public static byte[] GetFileContent(string fileName)
{
    CloudBlobContainer container = GetBlobContainer();           
    CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
    blockBlob.FetchAttributes();
    long fileByteLength = blockBlob.Properties.Length;
    byte[] fileContent = new byte[fileByteLength];
    for (int i = 0; i < fileByteLength; i++)
    {
        fileContent[i] = 0x20;
    }
    blockBlob.DownloadToByteArray(fileContent,0);
    return fileContent;
}

public ActionResult Download(string fileName)
{   
   byte[] fileContent = MyFileContext.GetFileStream(fileName);
   return File(fileContent, "application/zip", fileName);
}
Run Code Online (Sandbox Code Playgroud)

当我查看这两个选项时,我看到第一个需要在服务器磁盘中创建一个文件,而第二个将Blob中的数据存储在消耗内存的字节数组中.在我的特定情况下,我将处理大约150 MB的文件大小.

鉴于环境(环境,文件大小......)您认为哪种方法最好?

Gau*_*tri 30

您可以直接从blob存储中下载blob,而不是通过服务器流式传输blob.我的回答建立在Steve的回复之上:在MVC3中下载Azure Blob文件.要直接从存储中下载blob,您可以使用Shared Access Signature (SAS).最近,Azure Storage引入了一项增强功能,允许您Content-Disposition在SAS中指定标头.查看此修改后的代码.

    public static string GetDownloadLink(string fileName)
    {
        CloudBlobContainer container = GetBlobContainer();
        CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
        //Create an ad-hoc Shared Access Policy with read permissions which will expire in 12 hours
        SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy()
        {
            Permissions = SharedAccessBlobPermissions.Read,
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(12),
        };
        //Set content-disposition header for force download
        SharedAccessBlobHeaders headers = new SharedAccessBlobHeaders()
        {
            ContentDisposition = string.Format("attachment;filename=\"{0}\"", fileName),
        };
        var sasToken = blockBlob.GetSharedAccessSignature(policy, headers);
        return blockBlob.Uri.AbsoluteUri + sasToken;
    }

    public ActionResult Download(string fileName)
    {
        var sasUrl = GetDownloadLink(fileName);
        //Redirect to SAS URL ... file will now be downloaded directly from blob storage.
        Redirect(sasUrl);
    }
Run Code Online (Sandbox Code Playgroud)

  • 我的示例中的共享到期时间仅用于演示目的.您应该根据您认为用户下载文件所需的时间来设置它.如果您认为,您的用户可以在30秒内下载该文件,您可以将其设置为该值.您可能需要阅读此博客文章以了解SAS最佳实践:http://blogs.msdn.com/b/windowsazurestorage/archive/2012/06/12/introducing-table-sas-shared-access-signature-queue-sas -and更新到BLOB,sas.aspx.HTH. (3认同)

Rob*_*evy 20

Stream的好处在于,您可以在下载时逐个处理位,而不是构建一个大字节[]然后对整个操作进行操作.由于您正在写入文件然后将该完整文件读入内存,因此您对Stream的使用并没有真正获益.流API的一个很好的用途是将下载流直接传递给请求的响应流,如下面的答案所示.在MVC3中下载Azure Blob文件


Zyg*_*tas 15

如果您计划使用DownloadToBytesArray(异步或非异步),则必须首先获取blob属性以获取字节数组的初始大小.

如果您将使用DownloadToStream,则不必这样做.这是一个保存HTTP调用Blob存储,如果我没有记错,FetchAttributes()作为HTTP HEAD请求执行,将计为一个正常的交易(它会花费你换句话说一些钱).

  • 获取属性不会增加很多开销,但绝对值得一试. (3认同)