如何用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
相关产品推荐
相关产品推荐

