Lambda+S3 触发器创建缩略图
一、创建权限
创建 Lambda 函数,并对此策略授予了 Lambda 对 Amazon S3 存储桶的读取和写入权限,并允许其写入 Amazon CloudWatch Logs。
创建策略为:LambdaS3Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents",
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::*/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::*/*"
}
]
}
创建执行角色并附加权限策略(控制台)
打开(IAM)控制台的角色页面。
选择 Create role(创建角色)。
在可信实体类型中选择 AWS 服务,在使用案例中选择 Lambda。
选择下一步。
执行以下操作添加您在上一步中创建的权限策略:
在策略搜索框中,输入
LambdaS3Policy
。在搜索结果中,选中
LambdaS3Policy
的复选框。选择下一步。
在角色详细信息下的角色名称中输入
LambdaS3Role
。选择 Create role(创建角色)。
二、创建函数部署包
函数会生成同一个Bucket下不同路径的缩略图,并且会会创建相应的路径结构:
原来Bucket结构:resource/img/1.png
生成的目标Bucket结构:images+原来Bucket结构
import boto3
import os
import uuid
from urllib.parse import unquote_plus
from PIL import Image
s3_client = boto3.client('s3')
def resize_image(image_path, resized_path):
with Image.open(image_path) as image:
image.thumbnail(tuple(x / 2 for x in image.size))
image.save(resized_path)
def lambda_handler(event, context):
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = unquote_plus(record['s3']['object']['key'])
# 分割key,找到文件名前的目录部分
dir_path, filename = os.path.split(key)
# 构造新的key,添加'images'前缀并保持目录结构
new_dir_path = 'images/{}'.format(dir_path) if dir_path else 'images/'
new_key = os.path.join(new_dir_path, filename)
# 创建临时文件路径
tmp_filename = '{}-{}'.format(uuid.uuid4(), filename)
download_path = '/tmp/{}'.format(tmp_filename)
upload_path = '/tmp/resized-{}'.format(tmp_filename)
# 下载图像,调整大小,并上传
s3_client.download_file(bucket, key, download_path)
resize_image(download_path, upload_path)
s3_client.upload_file(upload_path, bucket, new_key)
在创建 lambda_function.py
文件的同一目录中,创建一个名为 package
的新目录并安装 Pillow(PIL)库和 AWS SDK for Python (Boto3)。虽然 Lambda Python 运行时系统包含 Boto3 SDK 的一个版本,但建议您将所有函数的依赖项添加到部署包中,即使这些依赖项已经包含在了运行时系统中。有关更多信息,请参阅 Python 中的运行时系统依赖项。
mkdir package
pip install \
--platform manylinux2014_x86_64 \
--target=package \
--implementation cp \
--python-version 3.9 \
--only-binary=:all: --upgrade \
pillow boto3
Pillow 库包含 C/C++ 代码。通过使用 --platform manylinux_2014_x86_64
和 --only-binary=:all:
选项,pip 将下载并安装包含与 Amazon Linux 2 操作系统兼容的预编译二进制文件的 Pillow 版本。这可以确保无论本地构建计算机的操作系统和架构如何,部署包都能在 Lambda 执行环境中正常发挥作用。
创建包含应用程序代码和 Pillow 以及 Boto3 库的 zip 文件。在 Linux 或 MacOS 中,从命令行界面运行以下命令。
cd package
zip -r ../lambda_function.zip .
cd ..
zip lambda_function.zip lambda_function.py
三、创建函数
要使用控制台创建 Lambda 函数,首先要创建包含一些“Hello world”代码的基本函数。然后,通过上传在上一步中创建的 .zip 或 JAR 文件,将此代码替换为自己的函数代码。
打开 Lamba 控制台的函数页面。
确保您在创建 Amazon S3 存储桶所在的同一 AWS 区域 内操作。您可以使用屏幕顶部的下拉列表更改区域。
选择 Create function (创建函数)。
选择从头开始创作。
在基本信息中,执行以下操作:
对于 Function name(函数名称),请输入
CreateThumbnail
。在运行时系统中,根据您为函数选择的语言选取 Node.js 18.x 或 Python 3.9。
对于架构,选择 x86_64。
在更改默认执行角色选项卡中,执行以下操作:
展开选项卡,然后选择使用现有角色。
选择您之前创建的
LambdaS3Role
。
选择创建函数。
上传函数代码(控制台)
在代码源窗格中,选择上传自。
选择 .zip 文件。
选择上传。
在文件选择器中,选择 .zip 文件,然后选择打开。
选择保存。
四、配置 Amazon S3 来调用函数
重要
此程序将 Amazon S3 存储桶配置为每次在此存储桶中创建对象时调用您的函数。请确保仅在源存储桶上配置。如果您的 Lambda 函数在调用此函数的同一个存储桶中创建对象,则可以在循环中持续调用您的函数。这可能会导致您的 AWS 账户 产生额外费用。
配置 Amazon S3 触发器(控制台)
打开 Lambda 控制台的函数页面,然后选择函数 (
CreateThumbnail
)。选择 Add trigger。
选择 S3。
在存储桶下,选择自己的源存储桶。
在事件类型下,选择所有对象创建事件。
在递归调用下,选中复选框以确认知晓不建议使用相同的 Amazon S3 存储桶用于输入和输出。您可以阅读 Serverless Land 中的 Recursive patterns that cause run-away Lambda functions,进一步了解 Lambda 中的递归调用模式。
选择 添加。
在您使用 Lambda 控制台创建触发器时,Lambda 会自动创建基于资源的策略,授予您选择的服务调用函数的权限。
五、使用虚拟事件测试 Lambda 函数
使用虚拟事件测试 Lambda 函数(控制台)
打开 Lambda 控制台的函数页面,然后选择函数 (
CreateThumbnail
)。选择测试选项卡。
要创建测试事件,在测试事件窗格中,执行以下操作:
在测试事件操作下,选择创建新事件。
对于事件名称,输入
myTestEvent
。在模板中,选择 S3 Put。
将以下参数的值替换为您自己的值。
对于
awsRegion
,将us-east-1
替换为在其中创建 Amazon S3 存储桶的 AWS 区域。对于
name
,将DOC-EXAMPLE-BUCKET
替换为您自己的 Amazon S3 源存储桶的名称。对于
key
,将test%2Fkey
替换为您在步骤 将测试图片上传到源存储桶 中上传到源存储桶的测试对象的文件名。
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "us-east-1",
"eventTime": "1970-01-01T00:00:00.000Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "DOC-EXAMPLE-BUCKET",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"
},
"object": {
"key": "test%2Fkey",
"size": 1024,
"eTag": "0123456789abcdef0123456789abcdef",
"sequencer": "0A1B2C3D4E5F678901"
}
}
}
]
}