前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >构建AWS Lambda触发器:文件上传至S3后自动执行操作的完整指南"

构建AWS Lambda触发器:文件上传至S3后自动执行操作的完整指南"

原创
作者头像
泽霖
发布2024-02-08 22:50:02
1730
发布2024-02-08 22:50:02

在本篇文章中,我们将学习如何设计一个架构,通过该架构我们可以将文件上传到AWS S3,并在文件成功上传后触发一个Lambda函数。

该Lambda函数将下载文件并对其进行一些操作。一些可能的选项包括:

  • 生成完整大小图像的缩略图版本
  • 从Excel文件中读取数据
  • 等等

初始化项目

我们将使用AWS Sam进行此项目。我们将使用此项目的typescript设置的样板。

步骤1:

首先,我们需要一些实用函数来从S3下载文件。这些只是纯JavaScript函数,接受一些参数,如存储桶、文件键等,并下载文件。

我们还有一个实用函数用于上传文件。

代码语言:javascript
复制
import aws from 'aws-sdk';
import fs from 'fs';

const s3 = new aws.S3();

export class S3Utils {
    static downloadFileFromS3 = function (bucket: string, fileKey: string, filePath: string) {
        console.log('downloading', bucket, fileKey, filePath);
        return new Promise((resolve, reject) => {
            const file = fs.createWriteStream(filePath),
                stream = s3
                    .getObject({
                        Bucket: bucket,
                        Key: fileKey
                    })
                    .createReadStream();
            stream.on('error', reject);
            file.on('error', reject);
            file.on('finish', () => {
                console.log('downloaded', bucket, fileKey);
                resolve(filePath);
            });
            stream.pipe(file);
        });
    };

    static uploadFileToS3 = function (
        bucket: string,
        fileKey: string,
        filePath: string,
        contentType: string
    ) {
        console.log('uploading', bucket, fileKey, filePath);
        return s3
            .upload({
                Bucket: bucket,
                Key: fileKey,
                Body: fs.createReadStream(filePath),
                ACL: 'private',
                ContentType: contentType
            })
            .promise();
    };

    static cleanDownloadedFile = async (filePath: string) => {
        await fs.unlink(filePath, (err) => {
            console.log('temporary file deleted ');
        });
    };
}

最后,还有一个从本地机器上删除文件的函数。

步骤2:

然后,我们需要在src文件夹下添加实际的Lambda处理程序。

在此Lambda中,事件对象将是S3CreateEvent,因为我们希望在将新文件上传到特定S3存储桶时触发此函数。

注意:此函数用于读取 .xlsx 和 .csv 文件。如果要支持其他文件,你将需要将其添加到supportedFormats数组中。

代码语言:javascript
复制
import { S3CreateEvent, Context } from 'aws-lambda';
import path from 'path';
import os from 'os';
import { S3Utils } from '../utils/s3-utils';

const supportedFormats = ['csv', 'xlsx'];

function extractS3Info(event: S3CreateEvent) {
    const eventRecord = event.Records && event.Records[0];
    const bucket = eventRecord.s3.bucket.name;
    const { key } = eventRecord.s3.object;
    return { bucket, key };
}

exports.handler = async (event: S3CreateEvent, context: Context) => {
    try {
        const s3Info = extractS3Info(event);
        const id = context.awsRequestId;
        const extension = path.extname(s3Info.key).toLowerCase();
        const tempFile = path.join(os.tmpdir(), id + extension);
        const extensionWithoutDot = extension.slice(1);

        console.log('converting', s3Info.bucket, ':', s3Info.key, 'using', tempFile);
        if (!supportedFormats.includes(extensionWithoutDot)) {
            throw new Error(`unsupported file type ${extension}`);
        }
        await S3Utils.downloadFileFromS3(s3Info.bucket, s3Info.key, tempFile);
        // 进行你想要的文件操作
        // contentType = `image/${extensionWithoutDot}`;
        // await S3Utils.uploadFileToS3(OUTPUT_BUCKET, s3Info.key, tempFile, contentType);
        await S3Utils.cleanDownloadedFile(tempFile);
    } catch (err) {
        console.log(JSON.stringify(err));
    }
};

步骤3:

最后一部分是更新template.yaml文件。在这里我们添加了三个东西。

  • 一个S3存储桶,我们将在其中上传文件。
  • 当将新文件上传到桶中时,将触发Lambda。请注意在Events属性中指定事件将是s3:ObjectCreated。我们还在这里链接了桶。
  • 一个允许Lambda读取s3桶内容的策略。我们还将策略附加到函数的角色上。(为每个函数创建一个角色。所以LambdaThatWillReactToFileUpload函数将具有一个名为LambdaThatWillReactToFileUploadRole的角色。)
代码语言:yaml
复制
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS SAM demo Lambda react to file uploaded to s3

Globals:
    Function:
        Runtime: nodejs14.x
        Timeout: 30

Resources:
    S3BucketToRespond:
        Type: AWS::S3::Bucket
        Properties:
            BucketName: 'Dummy-Bucket'
    
    LambdaThatWillReactToFileUpload:
        Type: AWS::Serverless::Function
        Properties:
            CodeUri: src/s3-file-upload-reaction
            Handler: app.handler
            Events:
                FileUploadedToS3:
                    Type: S3
                    Properties:
                        Bucket: !Ref S3BucketToRespond
                        Events: s3:ObjectCreated:*

    ReadS3BucketPolicy:
        Type: AWS::IAM::Policy
        Properties:
            PolicyName: ReadS3BucketPolicy
            PolicyDocument:
                Version: '2012-10-17'
                Statement:
                    - Effect: Allow
                      Action:
                          - s3:GetObject
                      Resource:
                          - !Sub '${S3BucketToRespond.Arn}/*'
            Roles:
                - !Ref LambdaThatWillReactToFileUploadRole

我们添加了额外的策

略以避免循环依赖问题。至此,你将根据你所在的区域部署代码。

要部署应用程序,你首先配置环境。你可以在此处找到详细信息。

然后运行以下命令进行部署

代码语言:bash
复制
sam deploy --guided

测试

要测试它是否起作用,转到AWS S3控制台,上传文件并检查日志。

要从本地机器检查日志

代码语言:bash
复制
sam logs -n LambdaThatWillReactToFileUpload --stack-name sam-lambda-trigger-s3-file-upload --tail

然后你将在那里看到日志。

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档