我正在使用 Azure 函数、Azure Blob 存储和 React 前端构建文件管理工具。我可以显示有关 blob 及其以前版本的详细信息。我可以访问当前版本和以前版本的versiondId和ETag。
我认为允许用户删除以前版本的 blob 可能是一个很好的功能。如果以前的版本有上百个,而且文件很大,那么存储以前的版本可能会产生很大的成本。
我已在存储帐户上启用软删除和版本控制。
下面的代码片段非常适合使用 ETag 匹配条件删除当前版本。如果我将 ETag 替换为有效的先前版本,删除不会成功。
// Get a reference to a container where the blob is located
BlobContainerClient containerClient = _blobService.GetBlobContainerClient(deleteMessage!.ContainerName);
Dictionary<string, bool> deletedItemStatus = [];
// Get a reference to the blob you want to delete
BlobClient blobClient = containerClient.GetBlobClient(deleteMessage.Path);
foreach(var eTag in deleteMessage.ETags)
{
// TODO - this works perfectly well if we delete the current version using its ETag - but we cant delete previous versions...
deletedItemStatus.Add(eTag, await blobClient.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots, new BlobRequestConditions { IfMatch = new ETag(eTag) }, cancellationToken: token));
}
var deletedOK = deletedItemStatus.All(r => r.Value == true);
_logger.LogInformation("File Delete Operation completed successfully? : {Status}", deletedOK);
return deletedOK;
我得到的不是成功:
[2024-02-19T15:35:44.696Z] Status: 412 (The condition specified using HTTP conditional header(s) is not met.)
[2024-02-19T15:35:44.699Z]
[2024-02-19T15:35:44.701Z] ErrorCode: ConditionNotMet
[2024-02-19T15:35:44.702Z] Headers:
[2024-02-19T15:35:44.703Z]
[2024-02-19T15:35:44.704Z] Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
我知道 ETag 很好,因为我在这次调用之前刚刚收到它,如果我将它交换到当前版本的 ETag,它就可以工作。
我在这方面进展不快。有人有什么想法吗?开始认为它不支持,但 CoPilot 似乎认为它是,但代码示例不起作用!
如果我将 ETag 交换为有效的先前版本,则删除 没有成功。
错误信息是正确的。您收到此错误是因为您正在对基本 blob 执行条件删除,并且您使用的 ETag 与当前标记不匹配。
要删除 Blob 版本,您需要使用该 Blob 的版本 ID。仅使用 ETag 无法删除 Blob 版本。 ETag 可以用作附加条件,即仅当 ETag 匹配时才删除 blob 版本。
在 Andrew B 的评论的帮助下,我发现这段代码有效:
foreach(var version in deleteMessage.Versions)
{
// Get a reference to the blob you want to delete
BlobClient blobClient = containerClient.GetBlobClient(deleteMessage.Path).WithVersion(version.Value);
deletedItemStatus.Add(version.Key, await blobClient.DeleteIfExistsAsync(cancellationToken: token));
}
版本是我定义的字典。 Key 恰好是 ETag,Value 是 versionId。我目前没有使用 ETag,但我相信它们应该作为唯一的 ETag/版本对出现,因此使用 ETag 作为密钥似乎是合理的。