脚本的功能目的是获取容器中的 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);
}
如果由于奇怪的异常而失败 - 也有可能,因为 .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/