【问题标题】:Why does StartCopyAsync() throw 409 Conflict when GenerateIfNotExistsCondition used for destination?当 GenerateIfNotExistsCondition 用于目的地时,为什么 StartCopyAsync() 会抛出 409 Conflict?
【发布时间】:2017-06-16 12:20:34
【问题描述】:

如果目标帐户不存在,我想将 blob 复制到另一个存储帐户。但我一定是误读了StartCopyAsyncGenerateIfNot​Exists​Condition 上的文档,因为我认为我可以在一个电话中完成(无需在单独的电话中检查目的地是否存在),如下所示:

    await _targetClient.StartCopyAsync(
        _schemaBlob, 
        null, 
        _schemaBlob.Name, 
        AccessCondition.GenerateIfNotExistsCondition(), 
        null, 
        ContainerName, 
        cancellationToken);

但如果目标 blob 存在,它会抛出 409 Conflict。这难道不是AccessCondition.GenerateIfNotExistsCondition() 参数的意义在于确保在 blob 存在时操作不会执行任何操作吗?

怎么做才对?

【问题讨论】:

    标签: c# azure azure-storage azure-blob-storage


    【解决方案1】:

    但如果目标 blob 存在,则会引发 409 冲突。这不是 AccessCondition.GenerateIfNotExistsCondition() 参数的重点,以确保在 blob 存在时操作不会执行任何操作吗?

    在 Azure 存储服务端,它什么也不做,只返回 409 状态码。在您的客户端,如果返回码不等于 200,则会抛出异常。我建议你在代码中添加一个 try-catch blob,并且在 catch blob 中什么都不做。

    try
    {
        //put your copy code here
    }
    catch (StorageException ex)
    {
        //If the exception is 409, just skip the exception
        if (!ex.Message.Contains("409"))
        {
            throw ex;
        }
    }
    

    否则,您可以在执行复制命令之前检查目标 blob 是否存在。

    if (targetBlob.Exists())
    {
        //do the copy here
    }
    

    将此参数保留为空并初始化为我所做的行为是相同的。

    它可能在您的代码中包含一些错误。 AccessCondition 有 2 个,一个用于源 blob,另一个用于目标 blob。这是一个示例方法。如果将目标 AccessCondition 的值更改为 null。目标 blob 将被源 blob 覆盖。

    public static async void CopyBlob(Uri sourceBlob, CloudBlockBlob targetBlob, System.Threading.CancellationToken cancellationToken)
    {
       string text  = await targetBlob.StartCopyAsync(
           sourceBlob,
           //Source blob access condition, it will check whether the source is exist. If source doesn't exist, a exeception will throw.
           Access​Condition.GenerateIfExistsCondition(),
           //Target blob access condition, it will check whether the target is exist. If target blob exist, 409 error will occur.
           AccessCondition.GenerateIfNotExistsCondition(),
           null,
           null,
           cancellationToken);
    }
    

    这是我的测试代码。请注意,如果您的源容器是私有的,则需要为 StartCopyAsync 方法的第一个参数提供带有 SAS 的源 blob URI。

    Uri sourceUri = new Uri("Put your source blob uri with SAS");
    
    string targetConnectionString = "target blob connectionString ";
    CloudStorageAccount targetStorageAccount = CloudStorageAccount.Parse(targetConnectionString);
    // Create the blob client.
    CloudBlobClient targetBlobClient = targetStorageAccount.CreateCloudBlobClient();
    
    CloudBlobContainer targetContainer = targetBlobClient.GetContainerReference("mycontainer2");
    CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference("text1.txt");
    
    CopyBblob(sourceUri, targetBlob, new System.Threading.CancellationToken());
    

    【讨论】:

    • 好的,有道理,但我不确定访问条件的意义何在?留下这个参数null并初始化为我所做的行为是一样的。
    • 有什么更新吗?你试过我的建议了吗?如果您还有其他问题,请随时告诉我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2014-08-14
    • 1970-01-01
    • 2016-03-04
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多