背景
在工作中,绘制了一个canvas,并且画了一些图片在canvas上
在转为图片base64的时候报错了:
使用toDataURL
,提示:Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
原因定位
换了几个静态视频源,发现都有问题,我们做了几个测试进行排查:
- 会不会没配置CORS,查明这些资源在服务端已经配置了CORS跨域,也依然不行
- 是不是公司的亚马逊S3不行,更换了公司其他云存储服务商资源节点的也依然不行
- 资源标签设置了跨域属性也依然不行
- 在这个页面中,将视频挂载在其他除canvas外的dom上却没问题,能够正常导出不报错
- 从项目本地的资源却没有问题,能够正常导出不报错
而后推断出:
canvas的同源策略跨域更严格
,仅仅配置了CORS响应头还不够,还需要做到资源URL与当前域名一致,协议和域名和端口一致
解决方法
将你的图片资源转为blob地址后放入video
或者img
,而后绘入canvas即可
转化办法
/**
* 将指定 URL 的资源下载为 Blob 对象的地址
* @param {string} url - 要下载的资源的 URL
* @returns {Promise<string>} 包含 Blob 地址的 Promise 对象
*/
export const urlDownload2Blob = (url) => {
return new Promise((resolve, reject) => {
fetch(url)
.then(res => {
if (res.status !== 200) {
reject() // 如果响应状态不是200,则拒绝 Promise
}
return res
})
.then(res => res.blob()) // 将响应数据转换为 Blob 对象
.then(blob => {
// 兼容 Safari
window.URL = window.URL || window.webkitURL
// 将 Blob 对象转换为 Blob 地址
const blobUrl = window.URL.createObjectURL(blob)
resolve(blobUrl) // 解析 Promise 并返回 Blob 地址
})
})
}