You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS S3分片上传中如何通过If-Match ETag避免误覆盖?

AWS S3分片上传带If-Match条件实现方案

核心原理

AWS S3的分片上传中,If-Match条件需要在初始化分片上传(CreateMultipartUpload)阶段设置,而非在完成上传或TransferUtility的通用配置里。因为分片上传的整个生命周期从初始化请求开始,只有初始化时验证ETag匹配,后续的分片上传和完成操作才会生效;如果初始化时ETag不匹配,直接返回412 Precondition Failed,终止整个流程,避免误覆盖。


一、使用TransferUtility的正确实现

你之前的问题大概率是没在TransferUtility的上传请求中正确配置初始化阶段的请求头。以下是带If-Match条件的分片上传代码:

using Amazon.S3;
using Amazon.S3.Transfer;

var s3Client = new AmazonS3Client(Amazon.RegionEndpoint.YourRegion);

var uploadRequest = new TransferUtilityUploadRequest
{
    BucketName = "your-bucket-name",
    Key = "your-object-key",
    FilePath = "path-to-your-file",
    PartSize = 5 * 1024 * 1024, // 5MB分片大小,可按需调整
    Headers = new Amazon.S3.Model.S3Headers
    {
        IfMatch = "your-cached-etag" // 传入缓存的ETag值,注意保留双引号格式
    }
};

try
{
    var transferUtility = new TransferUtility(s3Client);
    await transferUtility.UploadAsync(uploadRequest);
    Console.WriteLine("上传成功,ETag匹配");
}
catch (AmazonS3Exception ex)
{
    if (ex.StatusCode == System.Net.HttpStatusCode.PreconditionFailed)
    {
        Console.WriteLine("ETag不匹配,终止上传");
    }
    else
    {
        Console.WriteLine($"上传失败:{ex.Message}");
    }
}

关键说明

  • TransferUtility会自动将Headers.IfMatch传递给初始化分片上传的请求,而非后续步骤。
  • 若ETag不匹配,S3直接返回412错误,TransferUtility抛出对应异常,不会执行任何分片上传或覆盖操作。

二、使用底层S3 API的正确实现

底层API需要手动完成初始化→上传分片→完成的流程,其中If-Match必须在CreateMultipartUploadRequest中设置:

using Amazon.S3;
using Amazon.S3.Model;
using System.Collections.Generic;

var s3Client = new AmazonS3Client(Amazon.RegionEndpoint.YourRegion);
string bucketName = "your-bucket-name";
string objectKey = "your-object-key";
string cachedEtag = "your-cached-etag";
string filePath = "path-to-your-file";
long partSize = 5 * 1024 * 1024; // 5MB分片

// 1. 初始化分片上传,设置If-Match条件
var initRequest = new CreateMultipartUploadRequest
{
    BucketName = bucketName,
    Key = objectKey,
    Headers = new S3Headers
    {
        IfMatch = cachedEtag
    }
};

CreateMultipartUploadResponse initResponse;
try
{
    initResponse = await s3Client.CreateMultipartUploadAsync(initRequest);
}
catch (AmazonS3Exception ex) when (ex.StatusCode == System.Net.HttpStatusCode.PreconditionFailed)
{
    Console.WriteLine("ETag不匹配,终止上传流程");
    return;
}

// 2. 上传分片(示例逻辑,需根据实际文件调整拆分逻辑)
var partETags = new List<PartETag>();
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
    long filePosition = 0;
    int partNumber = 1;
    while (filePosition < fileStream.Length)
    {
        long currentPartSize = Math.Min(partSize, fileStream.Length - filePosition);
        var uploadRequest = new UploadPartRequest
        {
            BucketName = bucketName,
            Key = objectKey,
            UploadId = initResponse.UploadId,
            PartNumber = partNumber,
            PartSize = currentPartSize,
            FilePosition = filePosition,
            InputStream = fileStream
        };

        var uploadResponse = await s3Client.UploadPartAsync(uploadRequest);
        partETags.Add(new PartETag(partNumber, uploadResponse.ETag));
        filePosition += currentPartSize;
        partNumber++;
    }
}

// 3. 完成分片上传
var completeRequest = new CompleteMultipartUploadRequest
{
    BucketName = bucketName,
    Key = objectKey,
    UploadId = initResponse.UploadId,
    PartETags = partETags
};

try
{
    await s3Client.CompleteMultipartUploadAsync(completeRequest);
    Console.WriteLine("上传完成");
}
catch (AmazonS3Exception ex)
{
    Console.WriteLine($"完成上传失败:{ex.Message}");
    // 可选:失败时清理已上传的分片
    var abortRequest = new AbortMultipartUploadRequest
    {
        BucketName = bucketName,
        Key = objectKey,
        UploadId = initResponse.UploadId
    };
    await s3Client.AbortMultipartUploadAsync(abortRequest);
}

关键说明

  • CompleteMultipartUploadRequest确实不支持设置If-Match,因为S3的API设计中,分片上传的条件约束是在初始化阶段确定的,完成阶段仅负责合并分片,不会再验证ETag。
  • 初始化请求失败(ETag不匹配)时直接终止流程,避免无效的分片上传操作。

常见问题排查

  1. TransferUtility设置If-Match后仍上传成功:
    • 检查是否误将If-Match设置到Metadata等其他属性,而非Headers.IfMatch。
    • 确认缓存的ETag格式正确(通常带双引号,如"abc123",需完整传入)。
  2. 初始化时ETag匹配,但完成时对象被修改:
    • 若分片上传过程中其他客户端修改了目标对象,S3在完成上传时会返回409 Conflict错误,需捕获该异常并终止流程,同时清理已上传的分片。

内容的提问来源于stack exchange,提问作者Naveen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:40:27