在 Amazon S3 上保存图像并使用 CloudFront 分发它们的最佳方式

Best way to save images on Amazon S3 and distribute them using CloudFront

我正在处理的应用程序 (nodejs) 有用户配置文件,每个配置文件可以有多个图像。我使用 S3 作为我的主要存储和 CloudFront 来分发它们。

问题是有时用户会上传大图片,我想做的是在下载图片时缩放图片(在 html img 标签或手机 phone 中查看)因为性能。

我不知道在将图像上传到 S3 之前是否应该缩放图像(可能使用 lwip https://github.com/EyalAr/lwip)或者有没有办法缩放图像或在通过以下方式下载图像时获得低质量图像云端?我读到 CloudFront 可以使用 Gzip 压缩文件,但也不推荐用于图像。

由于存储问题,我也不想将缩放+原始图像上传到 S3。

应该在客户端、服务器还是S3中完成?最好的方法是什么?

is there a way of scaling the image or getting a low quality image when downloading it through CloudFront?

没有这样的功能。如果您想要调整图像大小、重新采样、缩放、压缩等,您需要在将其保存到 S3 中的最终位置之前执行此操作。

请注意,我说的是它在 S3 中的 最终 位置。

一个解决方案是将图像上传到 S3 中的中间 位置,可能在不同的存储桶中,然后使用修改图像的代码调整大小并将其存储在最终 S3 位置,CloudFront 将代表下载用户从中获取它。

I've read that CloudFront can compress the files using Gzip but also not recommended for images.

图像从 gzip 压缩中受益很少,但 CloudFront 文档还指出 CloudFront doesn't compress anything that isn't in some way formatted as text,这往往从 gzip 压缩中受益更多。

I also don't want to upload a scaled + original image to S3 because of the storage.

我认为这是你的错误。

"Compressing" 图片不像压缩 zip 文件。压缩图像 有损 。您无法从压缩版本重建原始图像,因为此处讨论的图像压缩(根据定义)是故意丢弃图像中的信息,直到大小在所需范围内并且质量在可接受的范围内.图像压缩既是一门科学,也是一门艺术。如果您不保留原始图像,并且后来决定要修改图像压缩算法(要么是因为您后来认为尺寸仍然太大,要么是因为您认为原始算法过于激进,导致压缩率低得令人无法接受质量),您无法 运行 您的 already-compressed 图像在不进一步降低质量的情况下第二次通过压缩算法。

使用 S3 的 STANDARD_IA ("infrequent access") 存储 class 将原始图像的存储成本减半,以换取更昂贵的下载——因为这些图像很少会永远不会再次下载,因为只有您知道它们存储在存储桶中的 URL。

Should be done in client, server or S3?

无法完成"in" S3 因为S3 只存储对象。它不会操纵它们。

这还有两个选择,但在服务器上进行有多种选择。

当您说 "server," 时,您可能会想到您的网络服务器。这是一个选项,但此过程可能 resource-intensive,因此您需要在可扩展性计划中考虑到它。

GitHub 上有项目,例如 this one,旨在使用 AWS Lambda 执行此操作,它提供 "serverless" 按需执行代码。服务器上的代码 运行s,但它不是您必须配置或维护的服务器,也不是在它不活动时付费的服务器——Lambda 以 100 毫秒为增量计费。这是第二个选项。

在客户端上执行当然是一种选择,但似乎可能存在更多问题并且 error-prone,更不用说某些解决方案 platform-specific。

没有 "best" 方法来完成此任务。

如果您不熟悉 EXIF 元数据,您也需要熟悉它。除了 resampling/resizing,您可能还需要从 user-contributed 图像中去除一些元数据,以避免泄露您的用户可能没有意识到附加到他们的图像的敏感数据——例如 GPS 坐标照片拍摄的地方。一些网站还为其 user-submitted 图片添加水印,这也是您可能同时做的事情。

我会将图像存储在 STANDARD_IA 中的 S3 中,然后使用 Lambda 运行 nodejs 和 sharp 动态调整它们的大小以完成繁重的工作。 Google 做类似的事情我相信,因为你可以在任何维度请求你的个人资料 img。

AWS Networking & Content Deliver 博客有一个 post 可以为您提供很多您需要的内容。 Check it out here.

基本思路是这样的:

  1. 像往常一样将图像上传到 S3(如果需要,您可以 STANDARD_IA 以节省费用)
  2. 使用包含所需图像大小的查询参数向 Cloudfront 发送请求(即 https://static.mydomain.com/images/image.jpg?d=100×100)
  3. 使用 Lambda Edge 函数,您可以构建调整大小的图像并根据需要将它们存储在 s3 中,然后再通过 CDN 提供它们。创建调整大小的版本后,它始终在 S3
  4. 中可用
  5. Cloudfront returns 刚刚创建的新调整大小的图像。

需要多做一些工作,但它可以让您根据需要 want/need 调整大小。它还使您可以随时从 UI 灵活地更改要提供给客户端的 img 大小。这里有一些类似的 posts.. 有些甚至不使用 Cloudfront,而是通过 ApiGateway 作为中介来提供服务。

https://aws.amazon.com/blogs/compute/resize-images-on-the-fly-with-amazon-s3-aws-lambda-and-amazon-api-gateway/

https://github.com/awslabs/serverless-image-resizing