canvas 导出图片时的安全问题处理

当在canvas上绘制跨域图片并尝试导出时,会遇到安全问题,浏览器限制了canvas的数据读取。解决方法包括设置图片的crossorigin属性和服务器支持跨域,确保在使用图片数据时进行合法的跨域请求。

天气预报说北京还有暴雨,疫情又严重了,大家出门在外注意安全。

言归正传!

canvas 能做的事情太多了,也让我爱上了这门技术,这段时间对他投入了很大精力。

canvas 在绘制内容的时候,会创建一块画布,这块画布是干净的,此时,你可以往上面画文字、画图片、还可以画视频等。在绘制图片的时候,图片可能会来源于其它域名,比如:

在网页 https://wsy.com/index.html 

中创建一个 canvas 元素,在 canvas 上绘制一张图片,图片地址为 

https://image/suyan.png(不支持跨域),一旦把图片绘制到 canvas 上,当你使用 canvas.toDataURL() 时会报一个安全问题:

其实调用getImageData(),toBlob() 这些 api 也会报错。

关于这个问题,MDN 上也有描述:

The canvas's bitmap is not origin clean; at least some of its contents have or may have been loaded from a site other than the one from which the document itself was loaded.

解决这个问题核心思路是解决图片的跨域问题。

这里提个疑问,浏览器为啥要加入这个安全举措?可以把任何图片绘制到 canvas 上,但却不让把 canvas 导出?

在访问图片的时候,可以通过 crossorigin 来设置跨域访问图片,代码如下:

let image = new Image();
image.crossOrigin = 'anonymous';
image.addEventListener('load', () => {
    // image load success
});
image.addEventListener('error', () => {
   // image load error
});
image.src = src;

一旦设置 crossorigin 这个属性时,那么你的图片服务器必须支持跨域访问,否则将会报错:

解决这个问题让服务端支持跨域即可,如果服务端支持不了,可以通过 node 层写个代理:

const axios = require('axios');
const cors = require('cors');
const app = express();
// express 使用跨域插件
app.use(cors());
// 访问的图片域名,访问时添加参数 requrl,图片真正的地址
app.use('/img/content', (req, res) => {
    let url = req.query.requrl;
    axios.get(url, {
        responseType: 'arraybuffer'
    }).then(data => {
        res.set('Content-Type', 'image/jpeg');
        let content = Buffer.from(data.data, 'binary');
        res.end(content);
    });
});

其实不仅是图片,如果你在 canvas 中使用视频也会遇到这个问题。

总之,问题的核心是,你可以把任意网站的图片应用到你的网站,但是如果想使用图片中的数据,必须声明图片通过跨域访问,也就是说你用图片数据的时候,要和服务器打声招呼:'我要用你图片,帮忙加个白名单吧'。解决此类问题,归根结底是解决跨域问题。

看一看下面的文章,更进一步:

https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

长按关注

素燕《前端小课》

帮助 10W 人入门并进阶前端

官网:https://lefex.gitee.io/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值