xueqianban
xueqianban copied to clipboard
获取微信头像的 base64 数据
应用场景
- 前端生成一张图片, 一般是基于页面的内容(DOM)生成一张用于分享的海报形式的图片(例如通过
html2canvas
) - 特殊在于分享的图片要包含微信用户的头像(图片位于
thirdwx.qlogo.cn
域名, 没有转存到自己的域名下) - 微信用户的头像图片相当于页面是跨域的
原理
想要获取图片的 base64
数据, 我们大概都知道, 需要将图片绘制到 canvas
上, 再通过 toDataURL
方法拿到 DataURL
数据, 即 base64
的图片数据
结论与重点
- 图片必须支持
CORS
跨域 - 避免触发浏览器的缓存机制, 以免浏览器拿到的是缓存数据而没有携带
CORS
策略
示例
generate-wx-headimgurl-dom-image | gist
遇到的坑
- 当加载图片时, 如果开启了
crossOrigin
机制, 服务器必须遵循CORS
规范, 返回Access-Control-Allow-Origin
头, 否则会被浏览器阻止(cancel)掉, 触发onerror
回调- 由于微信头像默认加载时不会返回
CORS
规范, 只有在请求时开启Origin
才会返回CORS
规范的内容 - 在 PC 端浏览器上如果不使用
Disable cache
, 会加载图片失败, 触发onerror
回调 - 因此在移动端浏览器上测试会发现也是触发的
onerror
回调(因为我们在页面中先预览了一次微信用户的头像) - 如果需要解决这个问题, 可以在第一次加载微信用户头像的时候就开启
crossOrigin
机制(但不排除命中其他应用种下的缓存) - 例如:
<img src="http://thirdwx.qlogo.cn/xx/132" crossorigin="anonymous">
- 或者再次加载图片的时候带上随机参数, 避免浏览器缓存(这个方案更稳定靠谱)
-
- 由于微信头像默认加载时不会返回
- 加载跨域的图片时必须让浏览器执行跨域请求(CORS)(开启
crossOrigin
机制), 否则将跨域的图片绘制到canvas
上会导致canvas
被污染, 执行canvas.toDataURL
会因为安全风险而导致执行失败抛出异常 - 开启
html2canvas
的useCORS
选项, 理论上就是运用CORS
机制跨域加载图片- 但受缓存的影响, 生成的图片会没有微信头像
- 因此可以先自行获取到图片的
base64
数据, 替换掉图片的src
避免产生跨域的问题 - 如果开启
allowTaint
选项, 会导致生成图片失败
补充
关于在 HTTPS 的页面中加载 HTTP 的内容, 我们的印象中是所有的 HTTP 的内容都会被浏览器阻止
- 但事实并不是这样的, 例如我们常见的 CSS/JS/XHR 都会被浏览器阻止, 浏览器会给出 ERROR 级别的错误
- 注意: 早期的浏览器版本(我测试的 chrome 12 版本), 混合的 HTTP 内容都可以加载成功, 不会被浏览器屏蔽, 只是有警告
- 但发现图片内容是可以加载成功的, 不会被浏览器阻止, 由此可以推断出媒体类无代码执行权限的内容(即纯用于显示的内容)是不会被浏览器阻止的, 只是给出 WARN 级别的警告信息
在开发的过程中需要生成带微信头像的图片, 在 PC 端(因为开发习惯了使用
Disable cache
)测试都是可以的, 一到移动端就不行了, 试过很多办法后无果(〒_〒 绝望了...) 突发奇想将微信头像 URL 的 HTTPS 替换成 HTTP, 发现就能够获取到base64
的数据了, 很是诡异. 现在理清楚背后的故事, 原来是缓存在作怪, 只要不触发浏览器的缓存就能够通过 CORS 跨域机制获取到图片的base64
的数据
参考
感谢笔记