从 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 文件

在 azure blob 子容器中从本地上传 zip

使用 REST API 上传到 Azure Blob 存储时,Zip 档案损坏

Ionic Zip 密码设置在 azure blob 存储中,并为 zip 文件夹而不是文件设置最佳压缩

从未以任何格式压缩的 azure blob 存储下载文件夹

合并和压缩 Azure Blob 存储中的多个大文件