Azure C#WebJob存档块块Blob写入所有存档的图像为0字节

时间:2016-05-05 17:42:01

标签: c# azure azure-webjobs

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

经过一些研究后,我能够让WebJob触发并将图像添加到存档并将其上传回Blob存储。问题是所有文件都有零字节。我对C#中的Streams完全不熟悉,但是在我可以简单地管理数据的前提下运行,只需要将最终的归档流写回blob存储。

我的假设不正确吗?

我怀疑我的问题与循环浏览图像时的某些异步操作有关,这些图像在编写和上传档案之前从未完成。

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

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

1 个答案:

答案 0 :(得分:1)

看起来问题就在这里:

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

你的entryStream是你写的流,为了添加到zip文件(如果我正确理解你的代码) - 所以没关系。 但是,您正在创建一个新的 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;

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