Azure Blob Error: StorageException: The condition specified using HTTP conditional header(s) is not met
Azure Blob Error: StorageException: The condition specified using HTTP conditional header(s) is not met
所以我有一个功能,可以每 10 分钟从 blob 存储中下载文本并检查结果。这个功能可以 运行 几天。但它经常(大约每天)在完成并出现以下错误之前失败。
Caused by: com.microsoft.azure.storage.StorageException: The condition specified using HTTP conditional header(s) is not met.
我的代码很简单。
public String downloadTextBlob(CloudBlobDirectory dir, String filename) {
try {
return dir.getBlockBlobReference(filename).downloadText();
} catch (StorageException | IOException | URISyntaxException e) {
throw new WorkbenchRuntimeException(e.getMessage(), e);
}
}
我发布了同样的问题 here,我对讨论使用 OperationContext 解决问题的答案很感兴趣。但是问题不在 Java 上,答案也没有真正解释它实际上在做什么。
这是建议的解决方案(非 java 代码)
OperationContext context = new OperationContext();
context.SendingRequest += (sender, e) => {
e.Request.Headers["if-match"] = "*";
};
谁能解释一下这到底是做什么的?也许我可以如何在 Java 中复制它,我注意到 Java azure 存储 sdk 中有一个 OperationContext,我可以调用 .downloadText() 并将操作上下文作为参数。我只是不确定如何处理 OperationContext。
首先,我建议您在此处阅读 Azure Blob 存储中的条件 headers:https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations。
我没有查看 Java SDK 的源代码,但我的猜测是 downloadText()
操作在幕后执行多个操作。在第一个操作中,它获取 blob 的属性(如 blob 的长度等),在下一个操作中它实际下载 blob。作为第一个操作的一部分,它还获取 blob 的 etag,并将相同的 etag 传递给 if-match
header.
中的第二个操作
现在在第一次和第二次操作之间,blob 发生了一些变化,导致 etag 值发生变化。由于第二个请求仍然使用旧的 etag 值并且 etag 之间存在不匹配,因此您的请求失败 precondition failed
。 if-match
header 中存在 etag 指示存储服务执行操作 只有当 条件匹配(即 etag 匹配).由于 etag 不匹配,您会收到此错误。
要解决此问题,您需要使用以下 downloadText()
方法的替代方法:
并为 if-match
指定具有“*”值的访问条件,这实际上告诉存储服务忽略 etag 值。您可以在此处了解有关访问条件的更多信息:https://docs.microsoft.com/en-us/java/api/com.microsoft.azure.storage.accesscondition?view=azure-java-legacy.
您的代码类似于(未经测试的代码):
AccessCondition accessCondition = AccessCondition.generateIfMatchCondition("*");
并在您的 downloadText() 方法中使用此访问条件。
所以我有一个功能,可以每 10 分钟从 blob 存储中下载文本并检查结果。这个功能可以 运行 几天。但它经常(大约每天)在完成并出现以下错误之前失败。
Caused by: com.microsoft.azure.storage.StorageException: The condition specified using HTTP conditional header(s) is not met.
我的代码很简单。
public String downloadTextBlob(CloudBlobDirectory dir, String filename) {
try {
return dir.getBlockBlobReference(filename).downloadText();
} catch (StorageException | IOException | URISyntaxException e) {
throw new WorkbenchRuntimeException(e.getMessage(), e);
}
}
我发布了同样的问题 here,我对讨论使用 OperationContext 解决问题的答案很感兴趣。但是问题不在 Java 上,答案也没有真正解释它实际上在做什么。
这是建议的解决方案(非 java 代码)
OperationContext context = new OperationContext();
context.SendingRequest += (sender, e) => {
e.Request.Headers["if-match"] = "*";
};
谁能解释一下这到底是做什么的?也许我可以如何在 Java 中复制它,我注意到 Java azure 存储 sdk 中有一个 OperationContext,我可以调用 .downloadText() 并将操作上下文作为参数。我只是不确定如何处理 OperationContext。
首先,我建议您在此处阅读 Azure Blob 存储中的条件 headers:https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations。
我没有查看 Java SDK 的源代码,但我的猜测是 downloadText()
操作在幕后执行多个操作。在第一个操作中,它获取 blob 的属性(如 blob 的长度等),在下一个操作中它实际下载 blob。作为第一个操作的一部分,它还获取 blob 的 etag,并将相同的 etag 传递给 if-match
header.
现在在第一次和第二次操作之间,blob 发生了一些变化,导致 etag 值发生变化。由于第二个请求仍然使用旧的 etag 值并且 etag 之间存在不匹配,因此您的请求失败 precondition failed
。 if-match
header 中存在 etag 指示存储服务执行操作 只有当 条件匹配(即 etag 匹配).由于 etag 不匹配,您会收到此错误。
要解决此问题,您需要使用以下 downloadText()
方法的替代方法:
并为 if-match
指定具有“*”值的访问条件,这实际上告诉存储服务忽略 etag 值。您可以在此处了解有关访问条件的更多信息:https://docs.microsoft.com/en-us/java/api/com.microsoft.azure.storage.accesscondition?view=azure-java-legacy.
您的代码类似于(未经测试的代码):
AccessCondition accessCondition = AccessCondition.generateIfMatchCondition("*");
并在您的 downloadText() 方法中使用此访问条件。