文章目录
- 最基础的情况。可能是: 路径错误(相对/绝对路径混乱); 资源被删除或未上传; OSS/CDN 缓存未刷新; 拼接 URL 时丢失了参数(如签名 URL 过期)。 排查建议: 打开 Network 面板; 直接在浏览器地址栏访问图片 URL; 看返回码是否为 404 或 403。
- 很多图片或 CDN 都会校验 Referer,限制图片只能在指定域名下访问。如果请求来源不在白名单内,服务器会拒绝访问(403)。 典型症状: Network 状态码 403; 响应头中带有自定义防盗链提示。 解决办法: 通过后端代理请求; 或联系服务端将当前域加入 Referer 白名单。
- 如果返回头不是图片类型(例如 text/html),浏览器可能无法渲染; 如果设置了 Content-Disposition: attachment,浏览器会触发下载行为,但现代浏览器对图片通常会放行显示。
- 某些云存储(如 OSS / COS / S3)要求签名 URL 才能访问。签名过期后图片加载失败
- 如果页面设置了严格的 CSP 策略,例如: Content-Security-Policy: img-src https://static.example.com 那么任何不在允许列表内的图片都会被阻止。
- 一个通过 HTTPS 加载的页面,去请求**非 HTTPS(HTTP)**的资源。 User agents must rewrite insecure schemes to secure schemes before fetching the resource. This does not affect the DOM or the URL reflected to script. <!– 页面本身是 https://example.com –> <img src=”http://img.example.com/a.png”> 此时页面是安全的,但图片请求是不安全的,浏览器会认定为“混合内容”。
- 因为 HTTP 请求容易被中间人攻击。攻击者可以篡改图片、注入恶意脚本、或监听请求,从而破坏整个 HTTPS 页面的安全性。
- 类型 说明 浏览器行为 主动混合内容(Active Mixed Content) 能影响页面逻辑的内容,例如 <script>、<iframe>、XHR、CSS、WebSocket 🚫 直接阻止 被动混合内容(Passive Mixed Content) 不影响逻辑的内容,例如图片、音视频、CSS 背景图 ⚙️ 可能被升级或阻止
- 从 Chrome 80+ / Edge 79+ / Firefox 83+ 起,浏览器对某些被动混合内容启用了 “自动升级机制”。当页面是 HTTPS 时,如果 <img> 的地址是 HTTP,浏览器会尝试自动改为 HTTPS 重新加载。
- <!– 页面是 https://page.com –> <img src=”http://cdn.page.com/pic.png” /> 浏览器会自动尝试请求: https://cdn.page.com/pic.png 如果资源服务器支持 HTTPS,就会成功显示。如果不支持或证书无效,加载失败(显示裂图)。 注意浏览器在 network 面板请求的是 https 请求,但是 DOM 中还是现实的 http 地址,浏览器可不会自动修改你的 DOM。 那么问题来了,为啥 DOM 没变但是渲染的是 https? 因为 请求完成后,浏览器渲染的是“响应的二进制内容”,不是 URL 图片 <img> 加载流程其实是: DOM 给出 URL 字符串(http) Resource Loader 把它升级成 https 并发送请求 请求返回后产生一个 decoded image bitmap(解码好的位图) <img> 标签拿到的是 “图片数据对象”(Image Bitmap / Image Document) 把这个 bitmap 交给渲染引擎绘制在页面上 也就是说,渲染用的不是 URL,而是“图片数据”
- 因为 URL 升级只是加载规则(fetching rule)的结果,不是文档结构(DOM) 的改变。 浏览器的设计理念: DOM = 你的代码 Loaders = 浏览器的行为 浏览器永远不会篡改你的 DOM 代码,只在加载阶段更换 URL。
- 元素类型 是否会自动升级 <img> ✅ 是 <audio> / <video> / <source> ✅ 是 CSS 图片(background-image, border-image) ✅ 是 <script> / <iframe> / XHR ❌ 否,直接阻止 📘 官方文档参考:MDN: 混合内容(Mixed Content)
- 升级依赖浏览器支持; 如果资源使用了 IP、非标准端口或证书无效,不会升级; 如果页面设置了 CSP: Content-Security-Policy: upgrade-insecure-requests 则会强制所有 HTTP 请求都升级为 HTTPS 升级失败依然会导致裂图。
- 因为在 Chrome 80 之前(2020 年以前),浏览器并不具备“自动升级”行为,只是警告或阻止。现在的混合内容机制是新一代浏览器安全策略的演进结果。
- 不会触发混合内容,HTTP 页面加载 HTTPS 图片完全合法,只是页面本身不安全。
目录
- 一、什么是“裂图”?
- 二、常见的裂图原因汇总
- 2.1 图片资源不存在
- 2.2 图片服务器防盗链(Referer 校验)
- 2.3 响应头设置错误(Content-Type/Content-Disposition)
- 2.4 权限与签名失效
- 2.5 CSP 限制(Content-Security-Policy)
- 三、混合内容机制(Mixed Content)
- 3.1 混合内容是什么?
- 3.2 为什么要阻止混合内容?
- 3.3 混合内容的两种类型
- 3.4 可升级内容(Upgradable Content)
- 3.4.1 举例说明:
- 3.4.2 浏览器不会把< img src=""> 改成 https
- 3.5 哪些资源属于“可升级内容”
- 3.6 注意:不是“所有场景”都自动升级
- 3.7 为什么以前的说法是“不会自动改为 https”
- 3.8 HTTP 页面加载 HTTPS 图片会怎样?
- 四、其他容易忽略的裂图原因
- 4.1 跨域限制(Canvas 绘制)
- 4.2图片过大或加载超时
- 4.3服务端缓存头异常
- 五、排查与修复建议
- 六、总结
在前端开发过程中,我们几乎都遇到过这种情况:
页面中某张图片加载不出来,显示成一个小小的“裂图”图标。
这看似简单的问题,实际上可能由多种原因造成,尤其是在 HTTPS 环境下,混合内容机制(Mixed Content) 是最常见、也最容易被误解的根源之一。
本文将带你系统梳理裂图的各种原因、排查思路,并重点讲清楚混合内容的原理与浏览器行为。
“裂图”(broken image)是指浏览器尝试加载 <img> 标签的图片资源失败时的表现形式。
常见表现:
-
图片区域显示为灰底、叉号、占位符;
-
控制台出现
Failed to load resource或Mixed Content警告; -
Network 面板中图片请求状态码为 404 / 403 / blocked。
最基础的情况。可能是:
-
路径错误(相对/绝对路径混乱);
-
资源被删除或未上传;
-
OSS/CDN 缓存未刷新;
-
拼接 URL 时丢失了参数(如签名 URL 过期)。
排查建议:
-
打开 Network 面板;
-
直接在浏览器地址栏访问图片 URL;
-
看返回码是否为 404 或 403。
很多图片或 CDN 都会校验 Referer,限制图片只能在指定域名下访问。
如果请求来源不在白名单内,服务器会拒绝访问(403)。
典型症状:
-
Network 状态码 403;
-
响应头中带有自定义防盗链提示。

解决办法:
-
通过后端代理请求;
-
或联系服务端将当前域加入 Referer 白名单。
-
如果返回头不是图片类型(例如 text/html),浏览器可能无法渲染;
-
如果设置了 Content-Disposition: attachment,浏览器会触发下载行为,但现代浏览器对图片通常会放行显示。
如果返回头不是图片类型(例如 text/html),浏览器可能无法渲染;
如果设置了 Content-Disposition: attachment,浏览器会触发下载行为,但现代浏览器对图片通常会放行显示。
某些云存储(如 OSS / COS / S3)要求签名 URL 才能访问。
签名过期后图片加载失败
如果页面设置了严格的 CSP 策略,例如:
Content-Security-Policy: img-src https://static.example.com
那么任何不在允许列表内的图片都会被阻止。
这是前端 HTTPS 场景下导致“裂图”的核心原因之一。
这种情况一般控制台会报错:net::ERR_CERT_COMMON_NAME_INVALID
一个通过 HTTPS 加载的页面,去请求**非 HTTPS(HTTP)**的资源。
User agents must rewrite insecure schemes to secure schemes before fetching the resource.
This does not affect the DOM or the URL reflected to script.
<!-- 页面本身是 https://example.com -->
<img src="http://img.example.com/a.png">
一个通过 HTTPS 加载的页面,去请求**非 HTTPS(HTTP)**的资源。
User agents must rewrite insecure schemes to secure schemes before fetching the resource.
This does not affect the DOM or the URL reflected to script.
此时页面是安全的,但图片请求是不安全的,浏览器会认定为“混合内容”。
因为 HTTP 请求容易被中间人攻击。
攻击者可以篡改图片、注入恶意脚本、或监听请求,从而破坏整个 HTTPS 页面的安全性。
| 类型 | 说明 | 浏览器行为 |
|---|---|---|
| 主动混合内容(Active Mixed Content) | 能影响页面逻辑的内容,例如 <script>、<iframe>、XHR、CSS、WebSocket |
🚫 直接阻止 |
| 被动混合内容(Passive Mixed Content) | 不影响逻辑的内容,例如图片、音视频、CSS 背景图 | ⚙️ 可能被升级或阻止 |
从 Chrome 80+ / Edge 79+ / Firefox 83+ 起,浏览器对某些被动混合内容启用了 “自动升级机制”。
当页面是 HTTPS 时,如果 <img> 的地址是 HTTP,浏览器会尝试自动改为 HTTPS 重新加载。
<!-- 页面是 https://page.com -->
<img src="http://cdn.page.com/pic.png" />
浏览器会自动尝试请求:
https://cdn.page.com/pic.png
如果资源服务器支持 HTTPS,就会成功显示。
如果不支持或证书无效,加载失败(显示裂图)。
注意浏览器在 network 面板请求的是 https 请求,但是 DOM 中还是现实的 http 地址,浏览器可不会自动修改你的 DOM。
那么问题来了,为啥 DOM 没变但是渲染的是 https?
因为 请求完成后,浏览器渲染的是“响应的二进制内容”,不是 URL
图片
<img>加载流程其实是:
DOM 给出 URL 字符串(http)
Resource Loader 把它升级成 https 并发送请求
请求返回后产生一个 decoded image bitmap(解码好的位图)
<img>标签拿到的是 “图片数据对象”(Image Bitmap / Image Document)把这个 bitmap 交给渲染引擎绘制在页面上
也就是说,渲染用的不是 URL,而是“图片数据”
因为 URL 升级只是加载规则(fetching rule)的结果,不是文档结构(DOM) 的改变。
浏览器的设计理念:
-
DOM = 你的代码
-
Loaders = 浏览器的行为
浏览器永远不会篡改你的 DOM 代码,只在加载阶段更换 URL。
| 元素类型 | 是否会自动升级 |
|---|---|
<img> |
✅ 是 |
<audio> / <video> / <source> |
✅ 是 |
CSS 图片(background-image, border-image) |
✅ 是 |
<script> / <iframe> / XHR |
❌ 否,直接阻止 |
📘 官方文档参考:
MDN: 混合内容(Mixed Content)
-
升级依赖浏览器支持;
-
如果资源使用了 IP、非标准端口或证书无效,不会升级;
-
如果页面设置了 CSP:
-
Content-Security-Policy: upgrade-insecure-requests
-
则会强制所有 HTTP 请求都升级为 HTTPS
-
升级失败依然会导致裂图。
升级依赖浏览器支持;
如果资源使用了 IP、非标准端口或证书无效,不会升级;
如果页面设置了 CSP:
Content-Security-Policy: upgrade-insecure-requests
则会强制所有 HTTP 请求都升级为 HTTPS
升级失败依然会导致裂图。
因为在 Chrome 80 之前(2020 年以前),浏览器并不具备“自动升级”行为,只是警告或阻止。
现在的混合内容机制是新一代浏览器安全策略的演进结果。
不会触发混合内容,HTTP 页面加载 HTTPS 图片完全合法,只是页面本身不安全。
若 <img> 跨域加载资源后再画到 <canvas> 上,未设置 crossorigin 会触发安全限制。
大图未能在超时时间内返回,可能表现为裂图。
过期或 ETag 不匹配,导致 CDN 无法正确命中图片。
| 步骤 | 操作 | 检查内容 |
|---|---|---|
| 1 | Network 面板 | 查看状态码 / 请求协议(HTTP or HTTPS) |
| 2 | Console 控制台 | 搜索 Mixed Content 或 Failed to load resource |
| 3 | 直接访问 URL | 检查是否可用、证书是否有效 |
| 4 | 检查 CSP | 是否限制了 img-src 来源 |
| 5 | 检查响应头 | Content-Type、Referer、防盗链策略等 |
混合内容机制是现代浏览器为保证 HTTPS 安全性而做出的妥协与平衡。
对于前端开发者而言,理解它的升级与阻止逻辑,是解决“裂图”的关键。
| 类别 | 原因 | 浏览器行为 | 解决方案 |
|---|---|---|---|
| 资源不存在 | 404 | 裂图 | 修正路径 |
| 防盗链 | 403 | 裂图 | 调整 Referer 或代理 |
| HTTP → HTTPS 混合内容 | 被动混合内容 | 自动升级或阻止 | 改为 HTTPS |
| CSP 限制 | 阻止加载 | 裂图 | 修改策略 |
| Content-Type 错误 | 无法解析 | 裂图 | 服务端修正 |
| 签名 URL 失效 | 403 | 裂图 | 重新生成签名 |
到此这篇关于前端图片加载失败、 img出现裂图的原因超详细解析的文章就介绍到这了,更多相关前端图片加载失败原因内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- 前端图片加载错误的多种原因分析
- 前端图片懒加载的原理与3种实现方式举例
- js前端图片加载异常兜底方案
- 网页前端优化之滚动延时加载图片示例
