canvas.toDataURL()报错的解决方案全都在这了
报错详尽信息
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
关键词
canvas.toDataURL()
crossOrigin
Access-Control-Allow-Origin
前言
最近在做一个创意类的图片合成工具,大概齐就是通过拼接自定义的文字和图片信息生成一张商品图片类似的功能,项目中用到了fabric.js
这个画板库,最后一步在保存图片的时候报上面的一长串错误,墙内墙外搜了一遍,给出的解决方案都不全面,为避免同学们再次踩坑,于是有了此文
正文
我们在convertDOM2Image
时,如果DOM
内存在图片资源,该资源所在的web-server
是不支持跨域的,保存图片是不会成功的。
因此在排查问题时,首先要确定
web-server
是否允许跨域,我们以nginx
为例,response-header
内要存在Access-Control-Allow-Orgin:xxxx
(可以是*
,安全性要求比较高的可以根据主域名自定义)如果是
img
标签, 是否添加了crossorigin="anonymous"
, 如果是Image
对象,同样是否添加了改属性obj.crossOrigin='anonymous'
如果还不行,这里先不把答案放出来,我们先看看栗子
在接下来的栗子中我们会用到将Image
转换为canvas
对象的方法
function convertImageToCanvas(image) {
// 创建canvas DOM元素,并设置其宽高和图片一样
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
// 我们在实际的开发中,需要将抓换后的base64图片编码传输到后台图片服务器,由server直接存储或者生成一张图片;
// 所以会用到 toDataURL
console.log(canvas.toDataURL('image/jpeg'))
return canvas;
}
栗子1
本地未设置跨域允许选项crossorigin=anonymous
,web-server
未设置跨域允许选项
<div id="d1">
<img style="width: 300px;height: 240px;" src="http://es6.ruanyifeng.com/images/cover_thumbnail_3rd.jpg" alt="">
<p>本地未设置跨域允许选项crossorigin=anonymous,web-server未设置跨域允许选项</p>
</div>
<button onclick="setCanvas('d1')">canvas保存</button>
function setCanvas(DOMID) {
let img = document.getElementById(DOMID).querySelector('img')
document.body.appendChild(convertImageToCanvas(img))
}
很显然,报错
栗子2
本地标签内设置跨域允许选项, web-server
未设置跨域允许选项
这次连图片都出不来,直接报错
这个好理解,浏览器同源策略限制嘛
Access to image at 'xxxx' (redirected from 'xxxx') from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
栗子3
本地未设置跨域允许选项crossorigin=anonymous
, web-server
设置跨域允许选项
报错,妥妥的。
栗子4
本地标签内设置跨域允许选项crossorigin=anonymous
, web-server
设置跨域允许选项
<div id="d4">
<img style="width: 300px;height: 240px;" src="https://img.alicdn.com/tfs/TB1_uT8a5ERMeJjSspiXXbZLFXa-143-59.png" alt="" crossorigin="anonymous">
<p>本地设置跨域允许选项`crossorigin=anonymous`,`web-server`设置跨域允许选项</p>
</div>
<button onclick="setCanvas('d4')">canvas保存</button>
居然可以了,但是~如果在代码内设置跨域呢?
栗子5
function setCanvas(DOMID) {
let img = document.getElementById(DOMID).querySelector('img')
img.crossOrigin= 'anonymous'
document.body.appendChild(convertImageToCanvas(img))
}
报错
我看官方文档的意思是必须同步设置crossOrigin=anonymous
,该图片凭证才会被信任
This means that CORS is enabled and credentials are sent if the image is fetched from the same origin from which the document was loaded.
否则缓存的图像数据仍然会被画布视为有污染的跨源内容.
怎么办?重新取一遍图片呗,加个随机数,图片还是那个图片,不过加了个马甲,浏览器就不认识了
栗子6
function setCanvas(DOMID) {
let img = document.getElementById(DOMID).querySelector('img')
img.src =img.src+'?v='+Math.random()
img.crossOrigin= 'anonymous'
img.onload=()=>{
document.body.appendChild(convertImageToCanvas(img))
}
}
binggo, 完美解决
所以我们在开发过程中,新建图片,更换图片,还原图片等功能代码内,最好每一次都加个随机数,以保证源都是最新的,不走缓存
多说一点吧,关于fabric.js
的相关跨域配置见下方
let _fabricConfig = {
// ....
crossOrigin:'anonymous'
};
/* fabric对象 */
let _fabricObj = new fabric.Canvas(id, _fabricConfig);
// 新建图片对象时
let imgInstance = new fabric.Image.fromURL(url + '?v='+ Math.random(), img => {}, {crossOrigin: 'anonymous'})
// 动态更新图片时
let currentActive = _fabricInstance.getActiveObj();
currentActive.setSrc(randomURL, img =>{}, {crossOrigin: 'anonymous'})
canvas.toDataURL()报错的解决方案全都在这了的更多相关文章
- Canvas引入跨域的图片导致toDataURL()报错的问题的解决
本文介绍了Canvas引入跨域的图片导致toDataURL()报错的问题的解决,分享给大家,具体如下: [场景] 用户打开网页,则请求腾讯COS(图片服务器)上的图片js代码.使用canvas绘图. ...
- 关于Entity Framework中的Attached报错相关解决方案的总结
关于Entity Framework中的Attached报错的问题,我这里分为以下几种类型,每种类型我都给出相应的解决方案,希望能给大家带来一些的帮助,当然作为读者的您如果觉得有不同的意见或更好的方法 ...
- 新手常见的python报错及解决方案
此篇文章整理新手编写代码常见的一些错误,有些错误是粗心的错误,但对于新手而已,会折腾很长时间才搞定,所以在此总结下我遇到的一些问题.希望帮助到刚入门的朋友们.后续会不断补充. 目录 1.NameErr ...
- Mysql only_full_group_by以及其他关于sql_mode原因报错详细解决方案
Mysql only_full_group_by以及其他关于sql_mode原因报错详细解决方案 网上太多相关资料,但是抄袭严重,有的讲的也是之言片语的,根本不连贯(可能知道的人确实不想多说) 我总共 ...
- Win7下nginx默认80端口被System占用,造成nginx启动报错的解决方案
Win7下nginx默认80端口被System占用,造成nginx启动报错的解决方案 在win7 32位旗舰版下,启动1.0.8版本nginx,显示如下错误: [plain] 2012/04/0 ...
- Mac上PyCharm运行多进程报错的解决方案
Mac上PyCharm运行多进程报错的解决方案 运行时报错 may have been in progress in another thread when fork() was called. We ...
- 安装Redis-cluster-gem install redis报错的解决方案
错误描述: [root@eshop-cache01 local]# gem install redis ERROR: Loading command: install (LoadError) cann ...
- ELK报错及解决方案
ELK报错及解决方案 1.jdk版本问题 报错如下: future versions of Elasticsearch will require Java 11; your Java version ...
- web.xml配置文件中<async-supported>true</async-supported>报错的解决方案
为什么用到这个: ssh集成了cxf,当登录系统后,发现系统报错,控制台不断输出下面信息: 2016-05-05 11:05:06 - [http-bio-8080-exec-4] - WARN - ...
随机推荐
- ubuntu 代理设置
在学习工作中使用vagrant作为开发环境已经有很长一段时间了,使用ubuntu 作为开发系统 在使用中发现,即使修改了apt的source.list源文件,在面对一些开发中需要的软件工具的时候,不可 ...
- IO和流
I/O和流 I/O是Input和Output的缩写 从读写设备,包括硬盘文件,内存,键盘输入,屏幕输出,网路 输入输出"内容"(字节或文本) 流是对输入输出设备的一种抽象 从流中读 ...
- 极验验证码破解之selenium
这一篇写完很久了,因为识别率一直很低,没办法拿出来见大家,所以一直隐藏着,今天终于可以拿出来见见阳光了. 哈喽,大家好,我是星星在线,我又来了,今天给大家带来的是极验验证码的selenium破解之法, ...
- cooking和session
## Cookie ## # 基本概念: >> 用于保存一次会话中的记录,存放在客户端(浏览器); |-- "一次会话" |-- 当客户端打开一个界面时 被称作一次会话 ...
- MVC01
1.Controller 1) 添加: 在Controller目录右键进行添加,出现很多模式供选择,选择空的Controller,命名后新建.新建后Views 目录将同步生成相应名称的视图文件目录 均 ...
- 震惊,当我运行了这条Linux命令后,服务器竟然... (Linux中的删除命令)
震惊,当我运行了这条Linux命令后,服务器竟然... 0X00 写在前面 大家都听说过删库命令rm -rf /*,但是谁又真正实践过呢?但作为一个程序员,不看看这条命令执行后会发生什么,怎么能甘心呢 ...
- Bootstrap4 正式发布
历经三年开发,前端框架Bootstrap 4正式发布了.然而今天的Web世界已经和当初Mark Otto发布Bootstrap时的情况大为不同,一些开发者由此质疑它的更新是否还有意义 1.V4版本的主 ...
- Object-Oriented Programming Summary Ⅳ
目录 UML单元总结博客 总结本单元两次作业的设计 总结自己在四个单元中架构设计以及OO方法理解的演进 总结自己在四个单元中测试理解与实践的演进 总结自己的课程收获 立足于自己的体会给课程组提三个具体 ...
- Mac结合Docker开发
Mac结合Docker开发 前几天在看Java并发实战时,在Mac上写了一个示例,结果运行后无法按照书本上运行.主要是有些命令,在Mac和Linux是有区别的,比如top, Mac上是不支持-Hp,意 ...
- 神奇的 SQL 之 ICP → 索引条件下推
开心一刻 楼主:来,我们先排练一遍 小伙伴们:好 嘿.哈.嚯 楼主:非常好,就是这个节奏,我们开始吧 楼主:啊.啊.啊,疼 ! 你们是不是故意的 ? 回表与覆盖索引 正式讲 ICP 之前了,我们先将相 ...