从 azure blob 存储文件生成 Zip 文件
Posted
技术标签:
【中文标题】从 azure blob 存储文件生成 Zip 文件【英文标题】:generate a Zip file from azure blob storage files 【发布时间】:2013-09-22 00:59:52 【问题描述】:我的 Windows azure blob 存储中存储了一些文件。我想获取这些文件,创建一个 zip 文件并将它们存储在一个新文件夹中。然后返回 zip 文件的路径。 设置 zip 文件位置的权限,以便我的用户可以通过单击链接将 zip 文件下载到本地计算机
https://mystorage.blob.core.windows.net/myfiles/2b5f8ea6-3dc2-4b77-abfe-4da832e02556/AppList/isjirleq/mydocs1.doc
https://mystorage.blob.core.windows.net/myfiles/2b5f8ea6-3dc2-4b77-abfe-4da832e02556/tempo/xyz/mymusic.mp3
https://mystorage.blob.core.windows.net/myfiles/2b5f8ea6-3dc2-4b77-abfe-4da832e02556/general/video/myVideo.wmv
https://mystorage.blob.core.windows.net/myfiles/2b5f8ea6-3dc2-4b77-abfe-4da832e02556/photo/photo1.png
我希望能够遍历这些文件并将它们全部压缩在一起以创建一个新的 zip 文件
(https://mystorage.blob.core.windows.net/myzippedfiles/allmyFiles.zip
) 并返回 zip 文件的路径
我的 azure blob 中有大量文件。所以下载、压缩和上传它们不是一个好主意。
我该怎么做?我需要一些示例代码来做到这一点
【问题讨论】:
这个答案提到将它们放在 Azure 本地存储中,但没有具体解释如何......但是***.com/questions/8587660/… 【参考方案1】:通过使用 blob 流将文件直接压缩到输出流,我们已经(部分)解决了这个问题。这避免了下载压缩然后发送的问题,并避免了发生这种情况时的延迟(我们使用了 ICSharpZipLib,reference)。但这仍然意味着通过网络服务器路由流:
public void ZipFilesToResponse(HttpResponseBase response, IEnumerable<Asset> files, string zipFileName)
using (var zipOutputStream = new ZipOutputStream(response.OutputStream))
zipOutputStream.SetLevel(0); // 0 - store only to 9 - means best compression
response.BufferOutput = false;
response.AddHeader("Content-Disposition", "attachment; filename=" + zipFileName);
response.ContentType = "application/octet-stream";
foreach (var file in files)
var entry = new ZipEntry(file.FilenameSlug())
DateTime = DateTime.Now,
Size = file.Filesize
;
zipOutputStream.PutNextEntry(entry);
storageService.ReadToStream(file, zipOutputStream);
response.Flush();
if (!response.IsClientConnected)
break;
zipOutputStream.Finish();
zipOutputStream.Close();
response.End();
存储服务只是这样做:
public void ReadToStream(IFileIdentifier file, Stream stream, StorageType storageType = StorageType.Stored, ITenant overrideTenant = null)
var reference = GetBlobReference(file, storageType, overrideTenant);
reference.DownloadToStream(stream);
private CloudBlockBlob GetBlobReference(IFileIdentifier file, StorageType storageType = StorageType.Stored, ITenant overrideTenant = null)
var filepath = GetFilePath(file, storageType);
var container = GetTenantContainer(overrideTenant);
return container.GetBlockBlobReference(filepath);
【讨论】:
我知道这可能很难回答,但是根据文件的数量/大小,这需要多长时间?我正在考虑将一个装满 50-200 个图像(每个大约 5-7MB)的容器压缩成一个 zip 文件供某人下载。在我沿着这条路线走之前,我会很好奇你的经验是是否构建该拉链可能需要 30 秒、10 分钟甚至更长的时间? 在这种情况下,zip 文件直接写入响应流,因此实际上在写入文件流后立即开始下载。因此延迟可以忽略不计,只要您可以比下载数据更快地读取和压缩数据(在大多数情况下都可以)。这就是我们这样做的原因。 哇,它甚至没有向我注册你在该代码中流回响应,但这是有道理的。显然,这就是您最初所说的,现在我重新阅读了您的答案;)非常酷的方法! 对于 net core:使用response.Body
,确保安装 SharpZipLib 的预览版本(与 netstadnard 兼容)并删除出现语法错误的代码(例如 BufferOutput
)
我可以使用 azure 函数压缩文件并上传回 blob 存储吗?如果可能的话,你能提供一些见解吗?【参考方案2】:
由于 blob 存储“只是”一个对象存储,因此您需要将它们下载到某个地方(可能是网络/工作者角色或您的本地计算机),压缩它们,然后重新上传 zip文件。据我所知,这是唯一的方法。
【讨论】:
【参考方案3】:我认为您无法避免下载它们,将它们压缩到本地,然后再上传回来。
压缩实用程序仅适用于本地资源。 Azure 存储本身没有能够自行压缩某些文件的概念/能力
【讨论】:
【参考方案4】:我有 99% 的把握,您使用的任何 zip 库都需要本地资源/本地文件才能创建 zip 文件。
看看 Azure Local Storage for Worker Roles。
http://vkreynin.wordpress.com/2010/01/10/learning-azure-local-storage-with-me/
您将能够在您的工作角色中指定一定数量的本地存储空间,以保存进程中可访问的内容。
例如
//在你的配置中创建一个本地存储部分。
<WebRole name="...">
<LocalResources>
<LocalStorage name="myLocalStorage" sizeInMB="50"/>
</LocalResources>
</WebRole>
//然后将文件保存到本地存储
CloudBlobContainer container = blobClient.GetContainerReference("myfiles");
CloudBlob blob = container.GetBlobReference("2b5f8ea6-3dc2-4b77-abfe-4da832e02556/AppList/isjirleq/mydocs1.doc");
LocalResource myStorage = RoleEnvironment.GetLocalResource("myLocalStorage");
string filePath = Path.Combine(myStorage.RootPath, "mydocs1.doc");
blob.DownloadToFile(filePath);
将所有文件保存在 LocalStorage 中后,使用 ZipLibrary 将所有文件路径捆绑在一起
【讨论】:
我实际上建议为此目的使用Azure Drive
而不是本地存储。首先,Azure Drive
可以达到 1 TB(因此比本地存储大得多),其次,一旦写入驱动器,数据就会被持久化。
好吧,他说他想把它放回 BlobStorage 中。所以大概他不想坚持两次。但是,是的,假设他需要额外的空间,Azure 驱动器就可以工作。
我会跳过 Azure 驱动器。压缩操作是时间点的:将一些文件下载到本地磁盘,压缩,然后推回一个 blob。如果本地磁盘在操作过程中出现故障,不用担心 - 只需使用队列消息来持久化“压缩这些文件”命令。另外,如果您使用 Azure 驱动器,则每个角色实例需要一个磁盘;这似乎是付出了很多努力却几乎没有收获。
同意。您可以分配的最大存储量受特定 VM 大小的限制,因此使用“azure drive”的唯一原因是,如果您有特别大的 zip 文件/文件内容要由相对较小的工作人员角色处理【参考方案5】:
我认为您可以使用 webjob 或 worker 角色来执行此操作。当您收到用户的请求时,将此请求推送到队列中,然后将作业 ID 返回给用户。 Webjob 或工作角色从队列中获取请求,下载这些文件并压缩它们,然后将 zip 文件上传回存储 blob。前端代码可以使用 ajax roll polling 和 job id 在完成后获取真正的下载 url。
【讨论】:
【参考方案6】:我已经使用网站上的 JSZip 从 Azure Blob 存储下载多个文件
var urls = [
"images/20170420_145140.jpg",
"images/20170503_142841.jpg",
"images/20170503_084035.jpg"];
download()
urls.forEach(function (url)
JSZipUtils.getBinaryContent(url, function (err, data)
if (err)
throw err; // or handle the error
try
zip.file(count + ".jpg", data, binary: true );
count++;
if (count == urls.length)
zip.generateAsync( type: "blob" ).then(function (content)
FileSaver.saveAs(content, zipFilename);
);
catch (e)
console.log("errorrr...k", e)
);
);
【讨论】:
【参考方案7】:不要认为 azure 提供了任何开箱即用的压缩功能。如果您可能需要避免周转时间。使用后台工作者角色是一个好主意,它将从特定队列中挑选您的文件。压缩它们上传并存储 url你像 sql db 这样的地方。我在与 db 通信时做过类似的事情,所以你可以放心,它会很快工作,而用户不会意识到它实际上并没有发生在前端。
【讨论】:
以上是关于从 azure blob 存储文件生成 Zip 文件的主要内容,如果未能解决你的问题,请参考以下文章
从 Azure blob 存储下载所有文件,对其进行压缩并以 JAVA 格式上传 zip 文件
使用 REST API 上传到 Azure Blob 存储时,Zip 档案损坏