如何在 AWS 上构建支持 AVIF 的前端图片优化方案

一、为什么使用 AVIF 图片格式?

优势点

说明

高压缩率

在相似质量下,AVIF 文件比 JPEG/PNG/WebP 更小,能有效节省带宽和存储空间。

更高画质

即使在低码率下也能保持清晰细节,减少压缩带来的马赛克或模糊问题。

支持透明度

像 PNG 一样支持 Alpha 通道透明效果,且文件更小。

支持 HDR

支持高动态范围(HDR)色彩,亮部与暗部细节表现更出色。

支持动画

支持多帧动画,体积远小于 GIF,可实现流畅动画效果。

开源免费

基于开放标准,无需支付版权费用,适合广泛应用。

更好的色彩表现

支持更高位深(如 10 位、12 位色深),色彩过渡更加自然。

浏览器支持不断提升

已被 Chrome、Firefox、Safari、Edge 等主流浏览器广泛支持,兼容性持续提升。

采用 AVIF 图片格式,可以大幅提升网页加载性能、优化视觉体验,并有效降低服务器及流量成本。

二、图片上传为 PNG/JPG,为什么最终返回的是 AVIF?

我们上传至 AWS S3 桶中的图片文件,最初是以传统格式(如 PNG、JPG)存在的。但用户最终访问时,返回的是 AVIF 格式,主要是因为配置了以下动态处理流程:

  1. 拦截请求与格式判断

  • 当浏览器请求图片资源时,AWS 会拦截请求,检测浏览器是否支持 AVIF 格式。

  • 如果支持,将在 S3 中查找对应的 AVIF 文件。

2. 动态生成 AVIF 图片

- 如果 S3 桶中已有对应的 AVIF 图片,直接返回。

- 如果没有现成的 AVIF 图片,则根据用户请求的源图片(PNG/JPG),实时生成一张新的 AVIF 图片,并保存到 S3 桶中,随后返回给用户。

3. 兼容老浏览器

  • 如果浏览器不支持 AVIF,则直接返回原始格式的图片(如 PNG、JPG),确保访问兼容性。

三、替换同名图片后,是否还会访问到旧的 AVIF 图片?

不会。

为了避免用户访问到缓存中的老图片,系统在图片上传阶段进行了以下处理:

  • 当上传新的同名图片时,AWS 会自动检测并删除已有的同名 AVIF 图片资源。

  • 这样一来,旧版 AVIF 图片被清除。

  • 当用户下次访问时,因找不到旧的 AVIF 图片,系统会根据新的源图重新生成新的 AVIF 文件并返回。

  • 从而确保用户访问到的永远是最新版本的图片内容。

✅ 此机制有效避免了 CDN 缓存失效等待问题,大大简化了图片更新和运维管理流程。

四、我们访问的图片后缀明明是jpg 或者png 为什么我们下载下来是avif

  1. 浏览器发起请求,比如 GET https://yourdomain.com/path/image.jpg

  2. **请求头(Accept)**中会带上浏览器支持的图片格式,比如:

Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8

浏览器告诉服务器:"我可以接受 avif 格式哦!"

  1. Lambda@Edge 或 CDN(如 CloudFront)拦截了请求,根据请求头里的 Accept 判断,发现浏览器支持 avif,于是就做了智能格式替换:

  • 虽然你请求的是 image.jpg

  • 但是它在 S3 或缓存中找到了对应的 image.avif

  • 返回的时候,偷偷换了资源文件,返回的是 AVIF 内容

  • 当用户下次访问时,因找不到旧的 AVIF 图片,系统会根据新的源图重新生成新的 AVIF 文件并返回。

  • 从而确保用户访问到的永远是最新版本的图片内容。

  •  返回的 HTTP 响应里,重要的是Content-Type 头:

Content-Type: image/avif

浏览器收到的是一个 AVIF 格式的数据,虽然 URL 还是 .jpg,但实际上它知道应该用 AVIF 解码来展示。

为什么下载下来是 AVIF?

  • 你点右键下载时,浏览器是根据返回的 Content-Type 类型来确定文件格式的,不是根据 URL 后缀。

  • Content-Type: image/avif,所以浏览器保存成了 .avif 文件,即使链接上还是 .jpg

  • 浏览器内部已经知道这张图实际上是 AVIF 格式了。

总结一句话:

请求是 JPG,返回是 AVIF,靠的是 HTTP Content-Type,浏览器根据返回类型进行识别和保存。

五、补充说明

  • 动态生成 AVIF 图片一般通过 AWS Lambda@Edge 来实现,支持实时生成并自动回写存储。

  • 项目如果对首屏加载性能要求极高,可以结合 CDN 对 AVIF 图片进行缓存加速。

  • 建议统一规范图片命名,避免因频繁重名导致过多历史资源堆积,影响桶管理效率。

要通过 AWS Lambda@Edge 动态把 S3 上的 PNG、JPG 转成 AVIF 图片,基本思路是:

  • 拦截图片请求(比如 .jpg、.png)

  • 判断浏览器 Accept 请求头是否支持 image/avif

  • 如果支持:

  • 查询 S3 中是否已有对应 .avif 文件

  • 如果没有,就实时读取源图,转码成 .avif,存回 S3,再返回

  • 如果不支持:

  • 直接返回原图

下面是一个简单版的 Node.js(AWS Lambda@Edge)脚本示例:

const AWS = require('aws-sdk');
const sharp = require('sharp'); // sharp 用于图片处理// S3 客户端
const s3 = new AWS.S3({ region: 'your-bucket-region' });const BUCKET = 'your-bucket-name';exports.handler = async (event, context, callback) => {const request = event.Records[0].cf.request;const headers = request.headers;const uri = request.uri;console.log('Request URI:', uri);// 只处理 jpg/png 请求if (!uri.match(/\.(jpg|jpeg|png)$/i)) {return callback(null, request);}// 检查浏览器是否支持 AVIFconst acceptHeader = headers['accept'] ? headers['accept'][0].value : '';const supportsAvif = acceptHeader.includes('image/avif');if (!supportsAvif) {// 不支持 AVIF,直接返回原图console.log('Browser does not support AVIF');return callback(null, request);}// 构造 avif 文件的路径const avifUri = uri.replace(/\.(jpg|jpeg|png)$/i, '.avif');try {// 先检查 AVIF 是否已经存在await s3.headObject({Bucket: BUCKET,Key: decodeURIComponent(avifUri).substring(1), // 去掉开头的 /}).promise();// 已存在,修改请求路径,返回 avifconsole.log('AVIF exists, serving AVIF');request.uri = avifUri;return callback(null, request);} catch (error) {if (error.code !== 'NotFound') {// 其他异常console.error('Error checking AVIF file:', error);return callback(error);}console.log('AVIF not found, generating dynamically');// AVIF 不存在,读取源图const originImage = await s3.getObject({Bucket: BUCKET,Key: decodeURIComponent(uri).substring(1),}).promise();// 用 sharp 转 AVIFconst avifBuffer = await sharp(originImage.Body).avif({ quality: 50 }).toBuffer();// 写回 S3,生成新的 AVIF 文件await s3.putObject({Bucket: BUCKET,Key: decodeURIComponent(avifUri).substring(1),Body: avifBuffer,ContentType: 'image/avif',CacheControl: 'public, max-age=31536000', // 设置长缓存}).promise();// 修改请求路径,返回新的 AVIFrequest.uri = avifUri;return callback(null, request);}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81160.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++中的std::allocator

C中的std::allocator 文章目录 C中的std::allocator1.std::allocator1.1C中的placement new 和operator new1.2一个custom allocator的实现1.3使用std::allocator_traits实现allocator 1.std::allocator C中的std::allocator默默工作在CSTL中的所有容器的内存分配上&#xff0…

CodeBuddy编程新范式

不会写?不想写? 腾讯推出的CodeBuddy彻底解放双手。 示例 以下是我对CodeBuddy的一个小体验。 我只用一行文字对CodeBuddy说明了一下我的需求,剩下的全部就交给了CodeBuddy,我需要做的就是验收结果即可。 1.首先CodeBuddy会对任…

QML学习01(设置宽度、高度、坐标点、标题,信号与槽,键盘事件)

QML学习 1、前言2、QML3、QML和QWidget的区别3、QtQuick下的Windows应用4、总结 1、前言 记录一下QML学习的过程,方便自己日后回顾,也可以给有需要的人提供帮助。 2、QML QML是 Qt 框架中的一种声明式编程语言,专门用于快速设计和开发用户…

在VSCode中接入DeepSeek的指南

本文将介绍三种主流接入方式,涵盖本地模型调用和云端API接入方案。 一、环境准备 1.1 基础要求 VSCode 1.80+Node.js 16.x+Python 3.8+(本地部署场景)已部署的DeepSeek服务(本地或云端)1.2 安装必备插件 # 打开VSCode插件面板(Ctrl+Shift+X) 搜索并安装: - DeepSeek Of…

机器学习-计量经济学

机器学习 不要事前决定变量关系,关键是谁也不知道啊,机器学习学习的模型(那也不是真实的关系啊) 这就是自然学科的好处:只要不断的优化这个未知的东西(函数),然后在数据上&#xff…

五、Linux账号与权限管理

1、管理用户和组账号 1.1、用户 1.1.1、用户的概念及作用 在Linux系统中,用户(User)指的是可以访问系统资源的个体实体。每个用户都有一个唯一的用户账号,用于标识和管理其在系统中的活动和访问权限。 用户的重要性和功能: 身份认证和访问控制: 用户账号用于身份认证,确…

精益数据分析(61/126):移情阶段评分体系构建与实战案例解析

精益数据分析(61/126):移情阶段评分体系构建与实战案例解析 在创业的移情阶段,如何科学评估用户需求的真实性与紧迫性,是决定后续产品方向的关键。今天,我们结合《精益数据分析》中的评分框架,…

完成反射宇宙的最后一块拼图:泛型集合

反射,c#的黑科技,一手打造漂亮的,专属于自己的属性框 之前分享的: 如何写一个自定义属性控件的功能,但是只是对基础的类型,比如String,bool,int等,但是对list<T>,Vector<T>这种泛型集合类型支持的不是很好,刚好最近重新研究了一下,将这个非常重要的功能完成了. 效…

Redis--基础知识点--26--过期删除策略 与 淘汰策略

Redis 的过期策略和淘汰策略是内存管理的核心机制&#xff0c;分别用于处理键的自动失效和内存不足时的数据清理。以下是详细说明&#xff1a; 1 、过期删除策略&#xff08;Expiration Policy&#xff09; 处理已设置过期时间&#xff08;EXPIRE&#xff09;的键&#xff0c;…

第六天——贪心算法——字符串分隔

1. 题目 给定一个字符串 s&#xff0c;我们需要将其划分为尽可能多的部分&#xff0c;使得同一字母最多出现在一个部分中。 例如&#xff1a;字符串 "ababcc" 可以划分为 ["abab", "cc"]&#xff0c;但要避免 ["aba", "bcc&quo…

[原创](现代Delphi 12指南):[macOS 64bit App开发]: 注意“回车换行“的跨平台使用.

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…

Maven 插件参数注入与Mojo开发详解

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

扩增子分析|R分析之微生物生态网络稳定性评估之节点和连接的恒常性、节点持久性以及组成稳定性指数计算

一、引言 周集中老师团队于2021年在Nature climate change发表的文章&#xff0c;阐述了网络稳定性评估的原理算法&#xff0c;并提供了完整的代码。自此对微生物生态网络的评估具有更全面的指标&#xff0c;自此网络稳定性的评估广受大家欢迎。本文将介绍网络稳定性之节点和连…

人体肢体渲染-一步几个脚印从头设计数字生命——仙盟创梦IDE

人体肢体动作数据集-太极拳 渲染代码 # 初始化Pygame pygame.init()# 设置窗口尺寸 WINDOW_WIDTH 800 WINDOW_HEIGHT 600 window pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption("动作回放")# 设置帧率 FPS 30 clock pyg…

强化学习入门:马尔科夫奖励过程

文章目录 前言1、组成部分2、应用例子3、马尔科夫奖励过程总结 前言 最近想开一个关于强化学习专栏&#xff0c;因为DeepSeek-R1很火&#xff0c;但本人对于LLM连门都没入。因此&#xff0c;只是记录一些类似的读书笔记&#xff0c;内容不深&#xff0c;大多数只是一些概念的东…

腾讯开源实时语音大模型VITA-audio,92mstoken极速响应,支持多语言~

简介 VITA-Audio 是一个由腾讯优图实验室&#xff08;Tencent Youtu Lab&#xff09;、南京大学和厦门大学的研究人员共同开发的项目&#xff0c;旨在解决现有语音模型在流式生成&#xff08;streaming&#xff09;场景下生成第一个音频令牌&#xff08;token&#xff09;时的高…

测序的原理

Sanger 测序原理 https://v.qq.com/x/page/d0124c0k44t.html illumina 测序原理&#xff1a; https://v.qq.com/x/page/i0770fd7r9i.html PacBio 第三代 SMRT 单分子测序 https://v.qq.com/x/page/r03534cry7u.html Ion torrent 测序原理 https://v.qq.com/x/page/v01754s6r82.…

高项-逻辑数据模型

逻辑数据模型的核心理解 1. 定义与特点 逻辑数据模型&#xff08;Logical Data Model, LDM&#xff09;&#xff1a; 是一种抽象的数据结构设计&#xff0c;用于描述业务实体&#xff08;如客户、订单&#xff09;及其关系&#xff08;如“客户下单”&#xff09;&#xff0c…

《数字分身进化论:React Native与Flutter如何打造沉浸式虚拟形象编辑》

React Native&#xff0c;依托JavaScript语言&#xff0c;借助其成熟的React生态系统&#xff0c;开发者能够快速上手&#xff0c;将前端开发的经验巧妙运用到移动应用开发中。它通过JavaScript桥接机制调用原生组件&#xff0c;实现与iOS和Android系统的深度交互&#xff0c;这…

提高绳牵引并联连续体机器人运动学建模精度的基于Transformer的分段学习方法

合肥工业大学王正雨老师团队针对绳牵引并联连续体机器人的运动学建模提出一种基于Transformer网络的分段学习方法&#xff0c;该方法较传统建模性能卓越、精度更高。相关研究论文“Transformer-based segmented learning for kinematics modelling of a cable-driven parallel …