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

如何用Lambda(JavaScript/Node.js)同步新S3对象至其他S3账户

实现S3跨账户增量同步(类似aws s3 sync)的Lambda方案

核心思路

通过对比源桶与目标桶中对象的最后修改时间,仅复制以下两类对象:

  • 目标桶中不存在的新增对象
  • 源桶中最后修改时间晚于目标桶的更新对象

具体步骤与代码实现

1. 依赖准备(AWS SDK v3)

确保Lambda层或部署包包含AWS SDK v3的S3客户端:

npm install @aws-sdk/client-s3

2. 完整Lambda代码

import { S3Client, ListObjectsV2Command, HeadObjectCommand, CopyObjectCommand } from "@aws-sdk/client-s3";

const s3Client = new S3Client({ region: "你的区域" });
const SOURCE_BUCKET = "源账户的桶名";
const DESTINATION_BUCKET = "目标账户的桶名";
// 如果需要同步特定前缀,可设置此项,否则留空
const SYNC_PREFIX = "";

export const handler = async () => {
  // 1. 获取源桶所有对象(处理分页)
  const sourceObjects = await listAllObjects(SOURCE_BUCKET, SYNC_PREFIX);
  
  // 2. 遍历每个源对象,判断是否需要复制
  for (const sourceObj of sourceObjects) {
    const key = sourceObj.Key;
    const sourceLastModified = sourceObj.LastModified;
    
    try {
      // 检查目标桶中是否存在该对象
      const headCommand = new HeadObjectCommand({
        Bucket: DESTINATION_BUCKET,
        Key: key
      });
      const destObj = await s3Client.send(headCommand);
      
      // 对比最后修改时间,源更新则复制
      if (sourceLastModified > destObj.LastModified) {
        await copyObject(key);
        console.log(`更新对象: ${key}`);
      } else {
        console.log(`对象已最新,跳过: ${key}`);
      }
    } catch (err) {
      // 目标对象不存在,直接复制
      if (err.name === "NotFound") {
        await copyObject(key);
        console.log(`新增对象: ${key}`);
      } else {
        console.error(`处理对象 ${key} 出错:`, err);
      }
    }
  }
  
  console.log("同步完成");
};

// 分页获取S3桶所有对象的辅助函数
async function listAllObjects(bucket, prefix) {
  let allObjects = [];
  let continuationToken = null;
  
  do {
    const command = new ListObjectsV2Command({
      Bucket: bucket,
      Prefix: prefix,
      ContinuationToken: continuationToken
    });
    const response = await s3Client.send(command);
    
    if (response.Contents) {
      allObjects = [...allObjects, ...response.Contents];
    }
    
    continuationToken = response.NextContinuationToken;
  } while (continuationToken);
  
  return allObjects;
}

// 执行跨账户复制的辅助函数
async function copyObject(key) {
  const copyCommand = new CopyObjectCommand({
    Bucket: DESTINATION_BUCKET,
    Key: key,
    CopySource: `${SOURCE_BUCKET}/${key}`,
    // 如果需要保留源对象的元数据,添加此项
    MetadataDirective: "COPY"
  });
  
  await s3Client.send(copyCommand);
}

3. 权限配置要点

  • Lambda角色权限:需要附加包含s3:ListBucket(源桶+目标桶)、s3:GetObject(源桶)、s3:PutObject(目标桶)的IAM策略。
  • 源桶桶策略:需要允许Lambda角色的ARN访问源桶的对象,示例策略:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::目标账户ID:role/Lambda角色名"
      },
      "Action": ["s3:ListBucket", "s3:GetObject"],
      "Resource": [
        "arn:aws:s3:::源桶名",
        "arn:aws:s3:::源桶名/*"
      ]
    }
  ]
}

注意事项

  • 大对象处理:如果源对象超过5GB,CopyObjectCommand会失败,此时需要改用分段复制(CreateMultipartUpload、UploadPartCopy、CompleteMultipartUpload),可在代码中根据sourceObj.Size判断后处理。
  • 时区问题:S3返回的LastModified是UTC时间,对比时无需转换时区,直接用Date对象比较即可。
  • 触发方式:如果需要实时同步,可将Lambda绑定到源桶的PutObject/DeleteObject事件,仅处理变化的对象,避免全量遍历。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:57:14