Azure Blob storage: DownloadToByteArray VS DownloadToStream

本文关键字:VS DownloadToStream DownloadToByteArray Blob storage Azure | 更新日期: 2023-09-27 18:09:17

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

在学习过程中,我有两个解决方案;第一个基本上使用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);        
}

另一方面,我使用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);
}

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

给定的情况(环境,文件大小…),你认为哪种方法是最好的?

Azure Blob storage: DownloadToByteArray VS DownloadToStream

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

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

Stream的好处是你可以在下载时一点一点地处理比特,而不是建立一个大字节[],然后对整个东西进行操作。你对Stream的使用并没有真正得到好处,因为你是在写文件,然后把整个文件读到内存中。流API的一个很好的用途是将下载流直接管道到请求的响应流,如这里的答案所示下载Azure Blob文件在MVC3

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

如果你要使用DownloadToStream你就不需要这样做了。这是一个保存的HTTP调用blob存储,如果我没有弄错的话,FetchAttributes()作为HTTP HEAD请求执行,这将算作一个正常的事务(换句话说,它将花费你一些钱)。