一、背景
近期公司需要做一个分享功能,让用户可以保存当前 canvas 生成的图片到本地。同事在实现保存图片到本地的时候出现了如下异常 DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
并因此遇到了一系列问题,现在记录下来作为参考。
二、解决 Tainted canvases may not be exported
2.1 是什么问题?
搜索了一下该关键词就能出来解决方案
这里面提到了,出现这个问题的原因是当前域名与 canvas 中所绘制的远程图片地址不是同一个域名,触发了 CORS
安全策略,所以出现了跨域问题。canvas 画布中只要存在一个图片存在跨域问题就会导致整个画布数据无法导出。类似的接口如 toBlob()、toDataURL()等。
2.2 如何解决?
在 image
变量上添加以下属性即可 img.crossOrigin = 'anonymous'
。但同时引发出了另一个问题:Access to image at 'https://img.xxx.cn/images/abc.png' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
。
三、解决 image 添加 crossorigin=’anonymous’ 后的图片跨域问题 的问题?
3.1 为什么添加 crossorigin=’anonymous’ 后会出现跨域问题呢?
因为同一个 URL 地址在多个地方同时被使用到,而预加载的图片或者常规的 img 标签默认没有添加 crossorigin='anonymous'
,所以请求服务器后缓存到浏览器本地的资源缓存也不包含跨域信息。此时在 canvas 中使用 URL 图片,同时增加了跨域的设置,那么获取到的数据也不包含跨域信息,则导致与 canvas 中设置的跨域不符则出现了跨域问题
3.2 解决方案?
- 是为所有为同一个
URL
地址的图片都添加crossorigin='anonymous'
或者都不添加; - 是不需要跨域的图片不添加
crossorigin='anonymous'
,只在需要必须要添加的地方添加 crossorigin,
同时在图片 URL 后添加时间戳t=Date.now()
。