我一直在使用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);
}
另一方面,我使用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中的数据存储在消耗内存的字节数组中。在我的特定情况下,我将处理大约150 MB的文件大小。
鉴于环境(环境,文件大小......)您认为哪种方法最好?
答案 0 :(得分:26)
您可以直接从blob存储中下载blob,而不是通过服务器流式传输blob。我的答案建立在史蒂夫的回答之上:Downloading Azure Blob files in MVC3。要直接从存储中下载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);
}
答案 1 :(得分:18)
Stream的好处是你可以在下载时逐个处理比特,而不是构建一个大字节[],然后对整个事件进行操作。由于您正在写入文件然后将该完整文件读入内存,因此您对Stream的使用并没有真正获益。充分利用流API将下载流直接传递到请求的响应流,如此处Downloading Azure Blob files in MVC3
中的答案所示答案 2 :(得分:14)
如果您打算使用 DownloadToBytesArray (异步与否),则必须首先获取blob属性以获得字节数组的初始大小。
如果您将使用 DownloadToStream ,则无需执行此操作。 那个人保存了对blob存储的HTTP调用,如果我没弄错的话, FetchAttributes()作为HTTP HEAD请求执行,这将被视为正常的事务(它会花费你一些钱)换句话说,钱。)。