23

我有一些文件存储在我的 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 文件的路径

我的天蓝色 blob 中有大量文件。所以下载、压缩和上传它们不是一个好主意。

我怎样才能做到这一点?我需要一些示例代码来执行此操作

4

7 回答 7

37

通过使用 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);
        }
于 2013-12-13T12:26:56.110 回答
4

由于 blob 存储“只是”一个对象存储,因此您需要将它们下载到某个地方(可能是网络/工作者角色或您的本地计算机),压缩它们,然后重新上传 zip 文件。据我所知,这是唯一的方法。

于 2013-09-17T14:25:15.433 回答
3

我认为您无法避免下载它们,将它们压缩到本地,然后再上传回来。

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

于 2013-09-17T14:25:52.323 回答
3

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

于 2013-09-17T14:55:29.423 回答
0

我已经使用网站上的 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)
            }
        });
    });
}
于 2020-09-02T07:33:47.877 回答
0

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

于 2017-07-10T14:02:40.683 回答
-1

不要认为 azure 为压缩提供任何开箱即用的功能。如果您可能需要避免周转时间。使用后台工作人员角色是一个好主意,它将从某些队列中选择您的文件。压缩它们上传它们并为您存储 url 之类的地方sql db。我在与 db 通信时做过类似的事情,所以你可以放心,它会非常快地工作,而用户不会意识到它实际上并没有发生在前端。

于 2013-09-18T05:07:11.853 回答