使用Azure.Storage.Blob .NET SDK v12,我尝试将其附加到块Blob。根据各种文档,似乎执行此操作的方法是将以前提交的块ID列表连同新的块ID一起提交。我确保块ID的长度都相同。但是,当我尝试提交已经提交的块ID时,出现“ 400:指定的块列表无效”错误。
这里有一些简化的代码说明了问题:
// Create a blob container and a new block blob
string connectionString = @"...";
BlobServiceClient serviceClient = new BlobServiceClient(connectionString);
string containerName = Guid.NewGuid().ToString();
BlobContainerClient containerClient = serviceClient.CreateBlobContainer(containerName);
BlockBlobClient blobClient = containerClient.GetBlockBlobClient("some-blob");
// Stage and commit a block containing some dummy data
byte[] dummyData = new byte[1024];
byte[] firstBlockID = Encoding.UTF8.GetBytes("0");
string firstIDBase64 = Convert.ToBase64String(firstBlockID); // "MA=="
var stageResponse = blobClient.StageBlock(firstIDBase64, new MemoryStream(dummyData));
var responseInfo = stageResponse.GetRawResponse(); // 201: Created
var contentResponse = blobClient.CommitBlockList(new[] { firstIDBase64 });
responseInfo = contentResponse.GetRawResponse(); // 201: Created
// Stage a second block
byte[] secondBlockID = Encoding.UTF8.GetBytes("1");
string secondIDBase64 = Convert.ToBase64String(secondBlockID); // "MQ=="
stageResponse = blobClient.StageBlock(secondIDBase64, new MemoryStream(dummyData));
responseInfo = stageResponse.GetRawResponse(); // 201: Created
// Sanity check:
// Viewing the block list in the debugger shows both the committed block ID
// "MA==" and uncommitted block ID "MQ==", as expected.
BlockList blockList = blobClient.GetBlockList(BlockListTypes.All).Value;
// Commit both the previously committed block. and the new uncommitted one.
// This results in the the error:
// Status: 400(The specified block list is invalid.)
// ErrorCode: InvalidBlockList
blobClient.CommitBlockList(new[] { firstIDBase64, secondIDBase64 });
很好的问题!我认为问题出在CommitBlockList
方法的实现方式上。我在Fiddler中检查了请求/响应,这就是发送到存储服务的内容:
<BlockList>
<Uncommitted>MA==</Uncommitted>
<Uncommitted>MQ==</Uncommitted>
</BlockList>
[如果您注意到,即使已提交具有MA==
块ID的块,SDK仍将其作为Uncommitted
发送,这会引起问题。
然后,我查看了此方法here
的文档,这是我注意到的here
参数的内容:
指定未提交 Base64编码的块ID表示Blob服务应仅在未提交的阻止列表中搜索命名块。如果在未提交的阻止列表中找不到该阻止,它不会被写入blob的一部分,并且RequestFailedException将被抛出。
因为具有base64BlockIds
块ID的块已经提交,并且您将其作为未提交的块发送,所以Storage Service引发异常。
恕我直言,该方法的实现不符合MA==
REST API操作。考虑到完全有可能使用REST API这样做,应该修改SDK以考虑这种情况。我建议为此在Put Block List
上打开一个问题。