c# - Azure C# WebJob 归档 block Blob 集使用 0 字节写入所有归档图像

标签 c# azure azure-webjobs

脚本的功能目的是获取容器中的 Blob 名称数组。并创建一个 .ZIP 文件,稍后可以下载。

经过一些研究,我能够触发 WebJob,并将图像添加到存档中,然后将其上传回 Blob 存储。问题是所有文件都有零字节。我对 C# 中的流完全陌生,但一直在这样的前提下进行操作:我可以根据需要简单地通过管道传输数据,只需将最终存档流写回 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);
    }
}

最佳答案

看来问题出在这里:

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 在很大程度上违反了里氏替换原则 - 您可能需要这样做;

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;

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

关于c# - Azure C# WebJob 归档 block Blob 集使用 0 字节写入所有归档图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37056966/

相关文章:

c# - 为什么这个单元测试在比较两个 double 时会失败?

c# - mvvmcross Viewmodel.Initialize 在您可以挂接 InitializeTask.PropertyChanged 之前被触发

c# - 反射(reflection):FindMembers 返回空

azure - 这是一种以语法方式或使用 HTTP 调用取消已运行的 azure 逻辑应用程序的方法

c# - 如何在Azure中上传pfx证书并在C#中访问和使用它?

Azure WebJobs : difference between Console. WriteLine 和 logger.WriteLine

c# - 在 Service Fabric 应用程序中运行时 WebJob SDK 不工作

c# - 理解 SOLID 设计的单一职责原则

azure - 将音轨添加到现有 Assets (通过 Azure 媒体服务)

c# - Redis 缓存仅在异步方法中同步请求超时且异步请求响应缓慢