AWS Lambda 尝试将文件从 S3 存储桶复制到另一个 S3 存储桶时出现无效存储桶名称错误

Invalid bucket name error when AWS Lambda tries to copy files from an S3 bucket to another S3 bucket

我是 python 的新手。我有一个事件触发的 AWS Lambda 函数,它将文件从一个 S3 存储桶复制到另一个 S3 存储桶。我要复制文件的目标 S3 路径是:“dest_bucket/folder1/test”。当我尝试 运行 时它给了我这个错误:

无效的存储桶名称“dest_bucket/folder1/test”:存储桶名称必须匹配正则表达式“^[a-zA-Z0-9.-_]{1,255}$”或者是与正则表达式“^”匹配的 ARN arn:(aws).:(s3|s3-object-lambda):[a-z-0-9]:[0-9]{12}:accesspoint[/:][ a-zA-Z0-9-.]{1,63}$|^arn:(aws).*:s3-outposts:[a-z-0-9]+:[0-9]{12}:outpost[ /:][a-zA-Z0-9-]{1,63}[/:]访问点[/:][a-zA-Z0-9-]{1,63}$"

源存储桶没有任何文件夹结构。目标存储桶具有文件夹结构,需要将文件复制到“dest_bucket/folder1/test”下。错误发生在 lambda 函数中:“destination_bucket_name = 'dest_bucket/folder1/test”。因为,如果我简单地写下不带斜杠的目标存储桶名称,它就可以工作!知道我应该怎么写吗?

import json
import boto3
import os
import uuid

def lambda_handler(event, context):
    try:
        client = boto3.client('sts')
        response = client.assume_role(RoleArn='arn:aws:iam::xxx:role/xxx_lambda_role',RoleSessionName="lambda")
        session = boto3.Session(aws_access_key_id=response['Credentials']['AccessKeyId'],aws_secret_access_key=response['Credentials']['SecretAccessKey'],aws_session_token=response['Credentials']['SessionToken'])
        print(session)
        print("role has been assumed")
        
        s3_client = boto3.client("s3", aws_access_key_id=response['Credentials']['AccessKeyId'],aws_secret_access_key=response['Credentials']['SecretAccessKey'],aws_session_token=response['Credentials']['SessionToken'])
        #s3_client = boto3.client("s3")
        
        #base = read from parameter store
        #table_partion = read from file
        destination_bucket_name = 'dest_bucket/folder1/test'

        # event contains all information about uploaded object
        print("Event :", event)

        # Source bucket
        source_bucket_name = event['Records'][0]['s3']['bucket']['name']
        print(source_bucket_name)

        # Filename of object (with path)
        file_key_name = event['Records'][0]['s3']['object']['key']
        #file_key_name = 'empty_test.txt'
        print(file_key_name)

        # Copy Source Object
        copy_source_object = {'Bucket': source_bucket_name, 'Key': file_key_name}
        print(copy_source_object)

        # S3 copy object operation
        s3_client.copy_object(CopySource=copy_source_object, Bucket=destination_bucket_name, Key=file_key_name)


        return {
            'statusCode': 200,
            'body': json.dumps('S3 events Lambda!')
        }

    except Exception as e:
        print(e)
        raise e

来自文档:

存储桶名称的长度可以在 3 到 63 个字符之间,并且可以 仅包含 lower-case 个字符、数字、句点和破折号。

存储桶名称中的每个标签必须以小写字母或 数.

桶名不能包含下划线,以破折号结尾,有 连续句点,或在句点旁边使用破折号。

存储桶名称的格式不能为 IP 地址 (198.51.100.24).

https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-s3-bucket-naming-requirements.html

确保您只使用存储桶名称作为存储桶名称:) 至于“路径”,它在 S3 中真的是假的——唯一真实的东西是对象键。斜杠只是该名称中的字符,它们没有特殊含义。

您可以使用:

destination_bucket = 'dest_bucket'
destination_path = 'folder1/test/'

for record in event['Records']:
    source_bucket = record['s3']['bucket']['name']
    source_key = record['s3']['object']['key']

    copy_source_object = {'Bucket': source_bucket, 'Key': source_key}

    destination_key = destination_path + source_key
    s3_client.copy_object(CopySource=copy_source_object, Bucket=destination_bucket, Key=destination_key)

这将遍历事件中的所有传入记录。

然后它将创建一个对象,名称为 folder1/test/ + 源对象的名称 (Key)。