从 Azure Blob 存储文件生成 Zip 文件

本文关键字:Zip 文件 存储文件 Azure Blob | 更新日期: 2023-09-27 18:31:49

我有一些文件存储在我的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 Blob 存储文件生成 Zip 文件

我们已经通过使用 blob 流将文件直接压缩到输出流(部分)解决了这个问题。这避免了下载压缩然后发送的问题,并避免了发生这种情况时的延迟(我们使用ICSharpZipLib,参考)。但这仍然意味着通过 Web 服务器路由流:

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

由于 blob 存储"只是"一个对象存储,因此需要将它们下载到某个位置(可以是 Web/辅助角色或本地计算机),压缩它们,然后重新上传 zip 文件。据我所知,这是唯一的方法。

我认为您无法避免下载它们,在本地压缩它们并将它们上传回去。

压缩实用程序仅适用于本地资源。 Azure 存储本身没有能够自行压缩某些文件的概念/能力

我 99% 确定您使用的任何 zip 库都需要本地资源/本地文件才能创建 zip 文件。

请查看辅助角色的 Azure 本地存储。

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 将所有文件路径捆绑在一起

我认为您可以使用 webjob 或 worker 角色来做到这一点。收到用户请求时,将此请求推送到队列中,然后将作业 ID 返回给用户。Web 作业或辅助角色从队列中提取请求,下载这些文件并压缩它们,然后将 zip 文件上传回存储 Blob。前端代码可以使用带有作业 ID 的 ajax 滚动轮询,以便在完成后获取真正的下载 URL。

我已经完成了这个 使用JSZip从网站下载多个文件

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

不要认为 Azure 提供任何开箱即用的压缩功能。使用后台工作线程角色是一个好主意,它将从某个队列中挑选您的文件.zip他们会上传它们并将 url 存储在像 sql db 这样的地方。我在与 db 通信时也做了类似的事情,因此您可以放心,它会非常快速地工作,而不会让用户意识到它实际上并没有在前端发生。