使用 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 中创建一个存储桶。
有关创建存储桶和设置策略的说明,请参阅以下文章。
我在这里推荐这篇文章,因为它是我之前写的

我尝试使用 AWS 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 格式编写测试事件,可以
将其理解为 Lambda 函数从 S3 接收此 JSON 数据并执行相应的函数。
在本例中,我们将预先上传一个名为 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
加载中...
0票,平均分:0.00/10
9,090
X Facebook Hatena书签 口袋

这篇文章的作者

关于作者

寺冈由纪

我于 2016 年加入 Beyond,目前
担任基础设施工程师和 MSP(托管服务提供商)已有六年。我负责处理突发事件的故障排除,
并使用 AWS 等公有云设计和构建基础设施。最近,我一直在
Docker 和 Kubernetes 等容器基础设施。此外,
使用 HashiCorp 的 Terraform 和 Packer 等工具来构建和自动化
我还担任技术推广者的角色,在外部学习小组和研讨会上进行演讲。

・GitHub
https://github.com/nezumisannn

• 演讲邀约
:https://github.com/nezumisannn/my-profile

• 演示材料(SpeakerDeck)
https://speakerdeck.com/nezumisannn

・认证:
AWS认证解决方案架构师 - 助理级、
Google Cloud专业云架构师

返回顶部