因为海报封面也就是上方的图片是文章封面图片,而文章封面图片是一个php随机图片api,导致不知道什么原因,点击预览海报可以看的到封面图片,下载下来就是一片空白Σ(゚д゚;)

一开始以为是php渲染延迟问题,但是搞了半天延迟多少秒都还是空白(/TДT)/
后边ai查出来是跨域问题,然后先是搞了nginx反代,但是最终代出来的图片地址还是源地址,或者说api那边有个策略不能跨域所以不行。最后试了php转发缓存到本地在发送过来,经历几个版本,图片可以正常显示了,但是海报这边下载出来还是空白,f12显示没有响应信息,最后把响应头加上,下载出来的海报才终于有封面了(〜 ̄△ ̄)〜

历经一天的不懈排查(用的ai)(ai太弱智要一步一步引导查找问题),终于在今天0:12分搞定了,可喜可贺
ヾ(≧∇≦*)ゝ
贴一下ai写的总结
✅ 根本原因分析
1️⃣ 直接原因:Canvas 被跨域图片污染
html2canvas在绘制时,如果图片来自 不同源(即使同域名但协议/端口不同也算跨域),且没有正确的 CORS 头,Canvas 会被标记为 tainted。一旦 Canvas 被污染,调用
toDataURL()就会抛出安全错误,导致海报生成失败(空白或报错)。
2️⃣ 深层原因:PHP 代理没有返回 CORS 头
虽然你使用了
file.221331.xyz的 PHP 代理来拉取t.alcy.cc的图片,但 PHP 脚本没有返回Access-Control-Allow-Origin响应头。浏览器仍然认为图片是“跨域”的,因此 Canvas 仍然被污染。
3️⃣ 次要原因:图片未完全加载就开始截图
大尺寸图片(2606×1591)加载较慢,如果在图片未完成加载时就调用
html2canvas,可能导致绘制空白。
✅ 最终解决方案(必须全部满足)
✅ 方案一:PHP 代理必须返回 CORS 头(最关键)
在 image.php最顶部 添加:
phpphp
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET");
header("Access-Control-Allow-Headers: Content-Type");
header("Cache-Control: public, max-age=86400");✅ 方案二:前端图片必须声明 crossorigin="anonymous"
htmlhtml
<img crossorigin="anonymous" src="https://file.221331.xyz/image.php?u=...">✅ 方案三:等待图片完全加载后再截图
jsjs
var img = document.querySelector('.dshare-poster-cover img');
if (img.complete) {
startCapture();
} else {
img.onload = startCapture;
img.onerror = startCapture;
}✅ 方案四:保留 html2canvas的必要配置
jsjs
useCORS: true,
scale: 2,
backgroundColor: "#fff",
onclone: function(clonedDoc) {
clonedDoc.getElementsByClassName("dshare-poster-crad")[0].style.transform = "none";
clonedDoc.getElementsByClassName("dshare-poster-crad")[0].style.borderRadius = 0;
}✅ 最终可用的一行代码(已验证)
jsjs
$(".dshare-poster-download").off("click").on("click",function(e){e.stopPropagation();var t=$(".dshare-poster-crad"),img=t.find(".dshare-poster-cover img")[0];if(!img)return;function start(){var A=t.outerWidth(),e=t.outerHeight();r()(t[0],{height:e,width:A,useCORS:!0,scale:2,backgroundColor:"#fff",onclone(A){A.getElementsByClassName("dshare-poster-crad")[0].style.transform="none",A.getElementsByClassName("dshare-poster-crad")[0].style["border-radius"]=0}}).then(A=>{var e=document.createElement("a");e.href=A.toDataURL("image/png"),e.download="share-"+(+new Date)+".png",e.click(),$(".dshare-poster").click()})}img.complete?start():$(img).one("load",start).one("error",start)});✅ 为什么之前会失败?
✅ 现在状态
🎯 一句话总结
PHP 代理解决了图片来源问题,但缺少
Access-Control-Allow-Origin头导致 Canvas 仍然被跨域污染;加上 CORS 头 + 等待图片加载 + 正确配置 html2canvas,问题彻底解决。
海报封面系统修复完成
https://www.221331.xyz/archives/VtJphfkT
评论