使用 AWS Lambda 自动生成由 S3 图片上传触发的缩略图
![]()
目录
我叫寺冈,是一名基础设施工程师。
本文的主题是 AWS 服务之一“Lambda”。AWS
Lambda(无服务器代码执行和自动管理)| AWS
顺便说一下,它的发音是“lambda”。中间的“b”去哪儿了?
先不说这个……
类似的文章已经有很多了,我也不确定自己改了多少遍,但我还是尝试着做了
一些修改,算是自学的一种方式。
这次,我将使用lambda来生成缩略图。更多详情请见下方↓
■首先,“lambda”是什么?
好的,我们先来概览一下 Lambda。
和往常一样,我将引用 AWS 官方文档(
什么是 AWS Lambda - AWS Lambda - AWS 文档)。
AWS Lambda 是一种计算服务,可让您无需预置或管理服务器即可运行代码。
我明白了。Lambda
使用某种“事件”作为触发器来
执行预先注册的代码
此外,由于此事件会异步触发处理执行,
因此无需一直保持 EC2 实例运行。
这就是为什么您无需配置或管理服务器的原因。
“事件”这个词之前出现过几次,但
简单来说,它大概是这样的:
- 文件已上传到 S3 存储桶
当文件上传到 S3 存储桶时,
可以
当然,这不需要调用 EC2 实例上的 API,
仅使用 S3 和 Lambda 函数即可完成。
是的,如果你已经阅读了目前为止的内容和这篇博客的标题,你可能已经猜到了,但
我想做的是“当文件上传到 S3 存储桶时自动生成图像缩略图”……
■缩略图制作之旅
- 准备一个 S3 存储桶,用于上传图像。
- 编写 lambda 函数
- 测试该功能
- 设置 Lambda 触发器
- 操作检查
① 准备一个 S3 存储桶用于上传图片
首先,我们需要准备一个容器才能开始,所以我们快速在 S3 中创建一个存储桶。
有关创建存储桶和设置策略的信息,请参考以下文章。
我之前写过相关文章,所以借此机会再次推荐一下(
②编写 lambda 函数
现在,我们进入正题:编写 Lambda 函数。
我们将编写代码来实现“自动生成缩略图”的功能,并将其注册到 Lambda 库中。
代码可以用 Python 或 Node.js 编写,但
这次我们将遵循个人偏好,使用 Node.js(Python 的粉丝们请见谅)。
首先,点击“创建 Lambda 函数”按钮,您应该会看到以下界面。

在此屏幕上,选择 lambda 函数的蓝图。
他们已经为您准备了一个模板,我将非常感激地使用它。
首先,从运行时选择中选择“Node.js 6.10”。
至于蓝图,我想处理 S3,所以我将使用名为“s3-get-object”的函数。
当我点击蓝图时……

这将带您进入触发器设置界面。
| 桶 | 选择你在①中创建的存储桶。 |
|---|---|
| 事件类型 | 这次,我们想要执行“当图片上传时”的功能,所以我们选择 Put。 |
| 前缀 | 这次我们将直接上传到存储桶,所以就省略这一步。 |
| 后缀 | 该函数只会对文件名以“jpg”结尾的文件执行。 |
请勿勾选“启用触发器”复选框。
稍后在检查您将要编写的函数的运行情况后,再手动启用它。
输入完信息后,单击“下一步”。

这是您实际编写函数的界面。
这里有一个输入函数名称的字段,但您可以使用任何您喜欢的名称。
由于您在蓝图选择界面选择了“s3-get-object”,因此
从 S3 检索文件的代码已经编写完成。
'use strict'; console.log('加载函数'); const aws = require('aws-sdk'); const s3 = new aws.S3({ apiVersion: '2006-03-01' }); exports.handler = (event, context, callback) => { //console.log('收到事件:', JSON.stringify(event, null, 2)); // 从事件中获取对象并显示其内容类型 const bucket = event.Records[0].s3.bucket.name; const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); const params = { Bucket: bucket, Key: key, }; s3.getObject(params, (err, data) => { if (err) { console.log(err); const message = `从存储桶 ${bucket} 获取对象 ${key} 时出错。请确保对象存在,并且您的存储桶与此函数位于同一区域。`; console.log(message); callback(message); } else { console.log('内容类型:', data.ContentType); callback(null, data.ContentType); } }); };
但是,虽然可以直接从 S3 检索文件,
却无法生成缩略图。
让我们对这段代码进行一些修改。
'use strict'; console.log('加载函数'); var fs = require('fs'); var im = require('imagemagick'); const aws = require('aws-sdk'); const s3 = new aws.S3({ apiVersion: '2006-03-01' }); exports.handler = (event, context, callback) => { const bucket = event.Records[0].s3.bucket.name; const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); const params = { Bucket: bucket, Key: key, }; s3.getObject(params, (err, data) => { if (err) { console.log(err); const message = `从存储桶 ${bucket} 获取对象 ${key} 时出错。请确保对象存在,并且您的存储桶与此函数位于同一区域。`; console.log(message); callback(message); } else { var contentType = data.ContentType; var extension = contentType.split('/').pop(); console.log(extension); im.resize({ srcData: data.Body, format: extension, width: 100 }, function(err, stdout, stderr) { if (err) { context.done('调整大小失败', err); } else { var thumbnailKey = key.split('.')[0] + "-thumbnail." + extension; s3.putObject({ Bucket: bucket, Key: thumbnailKey, Body: new Buffer(stdout, 'binary'), ContentType: contentType }, function(err, res) { if (err) { context.done('对象插入错误', err); } else { callback(null, "对象插入成功"); } }); } }); } }); };
添加完成后,它会显示如下内容。整个过程
与从 S3 获取文件之前相同,但
获取的图像会使用 ImageMagick 调整大小,并将
处理后的图像作为缩略图上传回 S3。
编写完代码后,您需要按照以下所示配置 IAM 角色。
我们将跳过此步骤,直接使用模板自动创建一个新角色。
此处创建的角色将附加一个用于操作 S3 对象的策略,因此
如果您未正确配置该策略,则该功能将失败。
(由于 S3 访问权限不足而导致的“访问被拒绝”是常见情况。)

点击“下一步”将进入确认界面,请点击“创建函数”按钮。
之后将创建一个 lambda 函数。

您刚刚创建的函数会显示在列表中。
③ 功能运行测试
测试你的函数,确保它能正常工作。

从屏幕顶部的“操作”菜单中选择“设置测试事件”。

这将带您进入测试事件输入界面。
您需要以 JSON 格式编写测试事件,并将
此 JSON 数据视为 Lambda 函数从 S3 接收并执行的函数。
在本例中,我们将预先上传一个名为 test.jpg 的图像文件到 S3 存储桶,
然后测试 Lambda 函数在图像已上传的情况下是否正常工作。
我们还提供了一个用于此测试事件的模板,因此
我们使用 S3 Put 模板。
输入以下内容,然后单击“保存并测试”。
{ "记录": [ { "事件版本": "2.0", "事件时间": "1970-01-01T00:00:00.000Z", "请求参数": { "源IP地址": "*" }, "s3": { "配置ID": "testConfigRule", "对象": { "e标签": "0123456789abcdef0123456789abcdef", "序列器": "0A1B2C3D4E5F678901", "键": "test.jpg", "大小": 1024 }, "存储桶": { "arn": "arn:aws:s3:::lambda-img-resize", "名称": "lambda-img-resize", "所有者身份": { "主体ID": "EXAMPLE" } }, "s3模式版本": "1.0" }, "responseElements": { "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH", "x-amz-request-id": "EXAMPLE123456789" }, "awsRegion": "ap-northeast-1", "eventName": "ObjectCreated:Put", "userIdentity": { "principalId": "EXAMPLE" }, "eventSource": "aws:s3" } ] }

执行结果显示成功!
让我们检查一下S3存储桶的内容是否有任何变化。

是的,缩略图生成正常,就像什么都没发生过一样。
函数本身的执行似乎没有问题。
④设置 lambda 触发器
现在我们终于来到了最后阶段,我们将设置触发器。
到目前为止,这只是一个测试,所以
即使您在此阶段上传新图片,也不会生成缩略图。
我们需要设置一个触发器,以便在上传图片时自动执行该函数。
点击我们创建的 Lambda 函数中的“触发器”选项卡。

触发器本身是在创建函数时创建的,所以剩下的就是启用它。
点击“启用”。
⑤ 运行检查
现在我们实际上传一张图片到 S3 并进行检查。

……它已经制作完成了,太好了……
■概要
你觉得怎么样?
虽然需要写代码,有点复杂,但
好处是方便又有趣,因为不用 EC2 就能做到这么多。
这次我只是简单介绍了一下,不过我想尝试一些更高级的功能。
就这些,谢谢。

0