Flush 和 Write 调用的特定组合破坏了通过 OpenWrite 使用的 BlockBlob

Specific combinations of Flush and Write calls corrupts BlockBlob used via OpenWrite

我最近遇到了一个错误,或者至少是通过 .NET 客户端使用的 BlockBlob 的一个非常奇怪的行为。

基本上,写入和刷新的特定组合会损坏文件,如果您在写入后读回它,则响应流包含垃圾(更准确地说,它是截断和 最后写入字节的重复)。

重现(100% 机会):

腐败的例子:

var iterations = new List<byte[]?>()
{
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    null,
    new byte[] { 0xFF },
    new byte[] { 0xAA },
};

written: 00000000FFAA
read:        FFAAFFAA

成功范例:

var iterations = new List<byte[]?>()
{
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    null,
    new byte[] { 0x00 },
    new byte[] { 0xFF },
    new byte[] { 0xAA },
};

written: 00000000FFAA
read:    00000000FFAA

这里最奇怪的是,如果您在损坏后再写入 1 个字节,那么损坏就会消失。仅当您的 blob 文件以 write4+flush+write2 序列结尾时才会发生。

有人看到这样的东西吗?

完整代码

var containerClient = new BlobContainerClient(connectionSting, "test");

var blockBlobClient = containerClient.GetBlockBlobClient($"test{Guid.NewGuid():N}.data");

var iterations = new List<byte[]?>()
{
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    new byte[] { 0x00 },
    null,
    new byte[] { 0xFF },
    new byte[] { 0xAA },
};

var writeStream = blockBlobClient.OpenWrite(true, new Azure.Storage.Blobs.Models.BlockBlobOpenWriteOptions()
{
    HttpHeaders = new Azure.Storage.Blobs.Models.BlobHttpHeaders()
    {
        ContentType = "application/octet-stream"
    }
});

var writeMemStream = new MemoryStream();

for (var i = 0; i < iterations.Count; i++)
{
    var buffer = iterations[i];

    if (buffer is null)
    {
        writeStream.Flush();
        writeMemStream.Flush();
    }
    else
    {
        writeStream.Write(buffer, 0, buffer.Length);
        writeMemStream.Write(buffer, 0, buffer.Length);
    }
}

writeStream.Dispose();

var readMemStream = new MemoryStream();
var readStream = blockBlobClient.OpenRead(options: new Azure.Storage.Blobs.Models.BlobOpenReadOptions(false)
{
    Position = 0
});
readStream.CopyTo(readMemStream);
readStream.Dispose();

readMemStream.Position = 0;
writeMemStream.Position = 0;
var readArr = readMemStream.ToArray();
var writeArr = writeMemStream.ToArray();

if (!readArr.SequenceEqual(writeArr))
{
    System.Console.WriteLine("DIFFERENT");
    System.Console.WriteLine(string.Join("", writeArr.Select(q => q.ToString("X2"))));
    System.Console.WriteLine(string.Join("", readArr.Select(q => q.ToString("X2"))));
}
else
{
    System.Console.WriteLine("SAME");
    System.Console.WriteLine(string.Join("", writeArr.Select(q => q.ToString("X2"))));
    System.Console.WriteLine(string.Join("", readArr.Select(q => q.ToString("X2"))));
}

https://www.nuget.org/packages/Azure.Storage.Blobs/12.8.3

中也提供了此修复程序