Skip to content

怎么解决canvas中获取跨域图片数据的问题?

Posted on:2024年8月10日 at 17:06

背景

在一张图片添加相关文字,然后转化为base64数据,上传至服务器。当代码上线写完部署到测试环境,控制台报出如下错题:

Uncaught (in promise) DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported

这是因为页面在请求图片时产生跨域情况,canvas认为该图片数据为污染的数据,是不安全的数据,无法导出base64数据。

为什么 canvas 认为跨域图片数据为 污染的数据

当请求跨域图片数据,而未满足跨域请求资源的条件时。如果canvas使用未经跨域允许的图片的原始数据,这些是不可信的数据,可能会暴露页面的数据。

请求图片资源 - 同域

Request Headers带有cookie。图片数据是被canvas信任的。

请求图片资源 - 跨域

默认情况下,直接请求跨域图片。因为不符合跨域请求资源的条件,图片数据是不被canvas信任的。

为了解决图片跨域资源共享的问题, 元素提供了支持的属性:crossOrigin,该属性一共有两个值可选:anonymous 和 use-credentials,下面列举了两者的使用场景,以及满足的条件。

anonymoususe-credentials
用途匿名请求跨域图片资源,不会发送证书(比如cookie等)具名请求跨域图片资源,会携带证书数据
Request Headersoriginorigin、cookie
Response headersAccess-Control-Allow-OriginAccess-Control-Allow-Origin、Access-Control-Allow-Credentials
所需条件Access-Control-Allow-Origin 字段值需要包含请求域。Access-Control-Allow-Origin 字段值需要包含请求域,且不能为通配符 *。Access-Control-Allow-Credentials 字段值需要为 true,表明允许请求发送证书数据。

代码示例

// page origin is https://a.com

const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");

const img = new Image();
img.crossOrigin = "anonymous";
img.onload = function () {
  context.drawImage(this, 0, 0);
  context.getImageData(0, 0, img.width, img.height);
};
img.src = "https://b.com/a.png";

另外,跨域图片能正常裁剪(图片未转化成base64),应该满足三个条件:

主要原因是:

原文转自:https://fe.ecool.fun/topic/87408912-b244-4727-951c-65993c6dbcff