【问题标题】:Azure C# WebJob Archiving Set of Block Blobs Writes All Archived Images with 0 Bytes块 Blob 的 Azure C# WebJob 归档集以 0 字节写入所有归档图像
【发布时间】:2016-05-06 06:54:13
【问题描述】:

脚本的功能目的是在容器中接收一组 blob 名称。并创建一个可在以后下载的 .ZIP 文件。

经过一些研究,我能够触发 WebJob 并将图像添加到存档并将其上传回 Blob 存储。问题是所有文件都有零字节。我对 C# 中的 Streams 完全陌生,但一直在这样的前提下操作

我的假设是否不正确?

我怀疑我的问题与循环图像时的某些异步操作有关,在写入和上传存档之前,这些操作永远不会完成。

代码如下,任何帮助将不胜感激!

public static void ArchiveImagesTask(
        [QueueTrigger("download")] AssetImagesArchive assetImages,
        string id,
        string email,
        string container,
        string[] images,
        [Blob("{container}")] CloudBlobContainer sourceContainer,
        [Blob("downloads")] CloudBlobContainer targetContainer)
{

    using (var memoryStream = new MemoryStream())
    {
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
        {
            foreach (var image in images)
            {
                var blobInArchive = archive.CreateEntry(image, CompressionLevel.Optimal);
                var blob = sourceContainer.GetBlockBlobReference(image);

                using (var entryStream = blobInArchive.Open())
                using (var fileToCompressStream = new MemoryStream(blob.StreamWriteSizeInBytes))
                {
                    fileToCompressStream.CopyTo(entryStream);
                }
            }
        }

        var zip = targetContainer.GetBlockBlobReference($"{id}.zip");
        memoryStream.Seek(0, SeekOrigin.Begin);
        zip.UploadFromStream(memoryStream);
    }
}

【问题讨论】:

    标签: c# azure azure-webjobs


    【解决方案1】:

    看来问题出在这里:

    using (var entryStream = blobInArchive.Open())
    using (var fileToCompressStream = new MemoryStream(blob.StreamWriteSizeInBytes))
     {
          fileToCompressStream.CopyTo(entryStream);
     }
    

    您的entryStream 是您写入的流,以便添加到 zip 文件中(如果我正确理解您的代码) - 这很好。 但是,您正在创建一个新的 empty fileToCompressStream,其中没有任何内容;你只是传入一个整数,它是流的大小(我不明白它是如何编译的,但那是另一回事)。因此,您正在向 Zip 文件添加一个空流。

    应该可以用这个替换上面的三行(未测试);

    using (var entryStream = blobInArchive.Open())
    {
        blob.DownloadToStream(entryStream);
    }
    

    https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.blob.cloudblob.downloadtostream.aspx

    如果失败并出现奇怪的异常 - 它可能,因为 .Net 中的 Streams 在很大程度上违反了 Liskov 替换原则 - 你可能需要这样做;

    using (var entryStream = blobInArchive.Open())
    using (var fileToCompressStream = new MemoryStream(blob.StreamWriteSizeInBytes))
     {
          blob.DownloadToStream(fileToCompressStream);
          fileToCompressStream.Position = 0; // Not sure this is necessary
          fileToCompressStream.CopyTo(entryStream);
     }
    

    ...但只有在必要时才这样做;如果您这样做,您将在内存中获得整个文件的另一个副本。

    如果之后仍有问题,可能需要手动刷新一些流;您正在使用的 using 语句将调用流上的 Dispose 方法,应该刷新它们,但总是可能有人没有正确实现。

    附注

    您非常正确地包含了这一行:

    memoryStream.Seek(0, SeekOrigin.Begin);
    

    它将流中的指针设置回开头,这样当您上传它时,您实际上会向上发送数据。您可能想知道 MemoryStream 有一个稍微简单的方法来做到这一点,即:

    memoryStream.Position = 0;
    

    这对结果没有影响,我个人更喜欢这种语法。

    【讨论】:

    • 您先生,简直太棒了!到目前为止,第一次迭代最多可以处理 20 张图像。也感谢您提供更多详细信息!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多