Logo

AWS S3 实时图片Resize & 添加水印 手把手教学

avatar alex 04 Sep 2024

需求

近期OSS从阿里云迁移到了AWS S3,发现图片的各种处理效果都失效了,导致用户在APP加载商品列表比较缓慢。所以希望能够让用户在列表访问的是缩略图。

阿里云的图片只需要简单在路径上加参数即可实现resize,而AWS没有提供类似实现,只能采用其他方案。

经过调研发现,CloudFront + API Gateway + Lambda的实现能满足需求。使用Gateway 拦截用户请求,调用Lambda 解析请求参数并生成相应尺寸的图片提供给用户,CloudFront 作为缓存。

整体架构

image.png

流程描述:

  1. 用户通过CloudFront 请求Resized 尺寸的图片,如果图片存在,直接返回
  2. CloudFront 从S3 Bucket 请求资源;
  3. 请求尺寸的图片不存在,浏览器将被重定向(307)到API Gateway 端点(存储桶静态网站托管中配置)
  4. API Gateway 触发Lambda 函数
  5. Lambda 函数从S3 存储同下载原始图片,调整大小后,将图片上传回存储桶
  6. API Gateway 重定向(301) 到新创建的CloudFront URL

操作步骤

权限策略

  1. IAM -> 策略 -> 创建策略 -> 按下图指定权限 -> 下一步填写名称和描述创建即可
    image.png
{
    "Version": "2012-10-17",
    "Statement": [
         {
		"Effect": "Allow",
		"Action": [
			"logs:CreateLogGroup",
			"logs:CreateLogStream",
			"logs:PutLogEvents"
		],
		"Resource": "arn:aws:logs:*:*:*"
	},
	{
		"Effect": "Allow",
		"Action": "s3:PutObject",
		"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
	}]
}
  1. IAM -> 角色 -> 创建角色
    image.png
    image.png
    image.png

Lambda

  • Lambda -> 函数 -> 创建函数
  • 代码是基于nodejs18,这里要注意版本选择
  • 角色选择上面创建的角色

image.png
image.png

API Gateway

  • API Gateway -> API -> 创建API
  • REST API -> 构建
    image.png
  • 配置资源

    1. 创建方法(Lambda函数选择上面创建的函数)
      image.png
      image.png
    2. 创建资源
      image.png
      image.png
    3. 编辑集成
      image.png
      image.png
    4. 部署API
      image.png
      image.png
    5. 前往阶段列表,编辑第四步新建的阶段
      image.png
    6. 编辑成功后,复制该页面的URL, 下一步配置要用
      image.png

存储桶静态网站托管

  • S3 -> 存储桶 -> 点击目标存储桶 -> 属性
  • 页面拉到底部 -> 静态网站托管 -> 编辑(HostName填你上面复制的链接的域名)
    image.png

    [
      {
          "Condition": {
              "HttpErrorCodeReturnedEquals": "404"
          },
          "Redirect": {
              "HostName": "c7xxxx.execute-api.ap-southeast-2.amazonaws.com", 
              "HttpRedirectCode": "307",
              "Protocol": "https",
              "ReplaceKeyPrefixWith": "image?path="
          }
      }
    ]
    
  • 保存成功后,会得到终端节点,注意该节点链接是http,后续测试访问缩略图链接将会访问这个链接(先以http://test.s3-website-ap-southeast-2.amazonaws.com为例,下面将用该链接)
    image.png

上传代码

  • Lambda -> 函数 -> 目标函数
  • 代码 -> 上传 zip文件
  • 常规配置

image.png

  • 配置 -> 环境变量 -> 编辑(URL填静态网站托管的地址)
    image.png
  • 以上配置后就可以访问图片了,例如你bucket的图片路径为 image/test.jpg,你可以直接访问 http://test.s3-website-ap-southeast-2.amazonaws.com/750xAUTO/images/test.jpg

注:750xAUTO可以修改为想要的尺寸,但由于我的水印图片是200x56, 我将最小尺寸设置为250x100, 小于该尺寸会加水印失败

CloudFront

  • CloudFront -> 分配 -> 创建分配
    image.png
    image.png
  • 创建好之后需要等一会才能生效
  • 假设分配的域名为 https://dzupxxx.cloudfront.net,则图片访问路径为 https://dzupxxx.cloudfront.net/750xAUTO/images/test.jpg

自定义功能

  • 水印图片需要替换成你们自身的水印图
  • 关键代码位于zip文件的index.js,用了Sharp库来处理图片,目前只实现了Resize和加水印,如有需要,可根据Sharp文档定制其他功能。

image.png

总结

今天我们学习了如何使用 CloudFront + API Gateway + Lambda 来实现图片处理及访问。我们可以按照自己需求去灵活修改代码上传到Lambda,但要注意图片的处理时间,如果是比较复杂的图片处理,则需要修改Lambda配置的超时时间和内存。
而且Lambda支持多种编程语言,包括Node.js、Python、Java、Go、Ruby、.NET Core等,对开发者比较友好。

Tags
Lambda
CloudFront