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

S3同桶文件迁移问题:Lambda实现文件移至桶根目录

S3文件迁移Lambda函数修复方案

问题场景

我们在名为aftoem-resolver-group-data-1的S3桶中有如下文件结构:

aftoem-resolver-group-data-1
|- 2023-09-25 // 日期文件夹
  |- {AWS Glue生成的随机字符串}.csv

预期效果是将日期文件夹内的CSV文件复制到桶根目录(重命名为resolver_group-2023-09-25.csv),然后删除该日期文件夹及其中的文件,但当前Lambda运行后,文件被复制到了新的子文件夹中,未达到预期。

错误原因分析

  • 错误1:目标键生成逻辑错误:原代码中key[3:].partition("%")[0]的处理完全不符合需求,会把源文件的路径(包含斜杠)带入目标文件名,导致文件被写入子文件夹而非根目录。正确做法是从源文件路径中提取日期部分(文件夹名)。
  • 错误2:冗余且错误的路径处理:原代码调用list_objects_v2并使用response["Prefix"]作为复制源,完全没必要——事件中的key已经是源文件的完整路径,直接使用即可。
  • 错误3:缺失删除逻辑:原代码没有实现复制完成后删除源文件夹及文件的步骤。

修正后的完整代码

import boto3
import botocore
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

s3_client = boto3.client('s3')

def lambda_handler(event, context):
    logger.info("触发S3文件处理流程")
    
    # 从事件中提取源桶和源文件路径
    source_bucket = event['Records'][0]['s3']['bucket']['name']
    source_key = event['Records'][0]['s3']['object']['key']
    
    logger.info(f"源桶: {source_bucket}, 源文件路径: {source_key}")
    
    # 提取日期部分(文件夹名):拆分路径,取第一个部分
    date_folder = source_key.split('/')[0]
    # 生成目标文件名:根目录下的resolver_group-日期.csv
    target_key = f"resolver_group-{date_folder}.csv"
    
    logger.info(f"目标文件路径: {target_key}")
    
    try:
        # 复制源文件到目标路径
        s3_client.copy_object(
            Bucket=source_bucket,
            CopySource={'Bucket': source_bucket, 'Key': source_key},
            Key=target_key
        )
        logger.info("文件复制完成")
        
        # 删除源文件和日期文件夹(S3中文件夹是虚拟的,删除所有前缀为日期的对象即可)
        response = s3_client.list_objects_v2(Bucket=source_bucket, Prefix=f"{date_folder}/")
        if 'Contents' in response:
            # 批量删除对象
            delete_keys = [{'Key': obj['Key']} for obj in response['Contents']]
            s3_client.delete_objects(
                Bucket=source_bucket,
                Delete={'Objects': delete_keys}
            )
            logger.info(f"已删除日期文件夹 {date_folder} 及其中的文件")
            
    except botocore.exceptions.ClientError as error:
        logger.error(f"操作失败: {error}")
        raise
    except botocore.exceptions.ParamValidationError as error:
        logger.error(f"参数错误: {error}")
        raise
        
    return {"status": "success", "message": "文件迁移完成"}

代码说明

  • 目标路径生成:通过source_key.split('/')[0]精准提取日期文件夹名,确保目标文件直接存放在桶根目录,无多余子路径。
  • 简化复制逻辑:直接使用事件提供的完整源文件路径,避免冗余的list接口调用。
  • 完整删除流程:通过列出日期文件夹下所有对象并批量删除,实现S3中“删除文件夹”的效果(S3无真实文件夹,删除所有前缀匹配的对象即可)。
  • 优化异常处理:捕获异常后直接抛出,确保Lambda能正确上报错误状态,便于排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:14:54