前端 Canvas 导出带水印图片跨域问题

前端 Canvas 绘制跨域图片 (如第三方图片、CDN 图片、不同域名图片)并导出时,浏览器会触发Canvas 污染(tainted canvas) 安全限制,导致:

  • toDataURL() / toBlob() 直接报错
  • 无法导出图片、无法下载、无法上传

核心原因:Canvas 加载了未授权的跨域图片,浏览器禁止读取 / 导出画布内容


一、根本原因(一句话)

图片域名 ≠ 你的网页域名,且图片服务器未开启跨域允许 + 前端未配置跨域加载 → Canvas 被标记为 "污染",禁止导出。

二、最简单、最通用的解决方案(前端 + 服务端 两步)

1. 前端代码:给图片添加跨域属性(必须)

javascript 复制代码
// 1. 创建图片对象
const img = new Image();

// 2. ✅ 关键:开启跨域加载(必须放在 src 赋值之前)
img.crossOrigin = 'anonymous'; 

// 3. 设置图片地址
img.src = 'https://第三方域名/你的图片.jpg';

// 4. 图片加载完成后绘制 Canvas
img.onload = function () {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  
  canvas.width = img.width;
  canvas.height = img.height;
  
  // 绘制底图
  ctx.drawImage(img, 0, 0);
  
  // 绘制水印(文字/图片水印都可以)
  ctx.font = '24px Arial';
  ctx.fillStyle = 'rgba(255,255,255,0.5)';
  ctx.fillText('我的水印', 50, 50);

  // ✅ 现在可以正常导出,不会跨域报错
  const base64 = canvas.toDataURL('image/png'); 
  
  // 下载图片
  const a = document.createElement('a');
  a.href = base64;
  a.download = 'watermark.png';
  a.click();
};

2. 服务端配置:给图片资源开启跨域(必须)

必须让图片所在的服务器返回跨域头:

javascript 复制代码
Access-Control-Allow-Origin: *
常见服务器配置示例
Nginx
javascript 复制代码
location ~* \.(png|jpg|jpeg|gif|webp)$ {
    add_header Access-Control-Allow-Origin *;
}
CDN(阿里云 / 腾讯云 / 七牛云)

直接在控制台开启 跨域配置 CORS ,添加 * 或你的域名即可。

本地开发

使用本地图片 / 同域名图片,不会出现跨域

三、如果服务端不改配置?(叼他)

让后端把图片返回 Base64 字符串,前端直接绘制 Base64,完全没有跨域。

javascript 复制代码
// 后端返回的 base64 字符串
const base64Img = 'data:image/png;base64,iVBORw0KGgo...';

const img = new Image();
img.src = base64Img; // 无跨域
img.onload = () => {
  ctx.drawImage(img, 0, 0);
  // 正常导出
};

总结

  1. 核心问题:跨域图片污染 Canvas,导致无法导出
  2. 标准方案:前端 crossOrigin="anonymous" + 服务端开启 CORS
  3. 服务端不可改:用 Base64后端代理
  4. 避坑:crossOrigin 必须放在 src 之前
相关推荐
子兮曰17 小时前
Bun v1.3.14 深度解析:Image API、HTTP/3、全局虚拟存储与五十项变革
前端·后端·bun
kyriewen18 小时前
今天,百年巨头一次砍了9200人,而一个离职科学家的实话让全网睡不着觉
前端·openai·ai编程
问心无愧051318 小时前
ctf show web 入门42
android·前端·android studio
kyriewen18 小时前
老板逼我上AI,我偷偷在浏览器里跑LLaMA,省下20万API费
前端·react.js·llm
Beginner x_u19 小时前
前端八股整理(手写 02)|数组转树、数组扁平化、随机打乱一个数组
前端·数组·数组转树·数组扁平化
KaMeidebaby19 小时前
卡梅德生物技术快报|禽类成纤维细胞 FISH 实验:鸟类性别染色体基因定位技术实现与数据验证
前端·数据库·其他·百度·新浪微博
天若有情67319 小时前
前端高阶性能优化:跳出传统懒加载与预加载,基于用户行为做轻量预判加载
前端·性能优化
小小小小宇19 小时前
前端转后端:SQL 是什么
前端
张元清20 小时前
React Observer Hooks:7 种监听 DOM 而不写样板代码的方式
前端·javascript·面试
广州华水科技20 小时前
单北斗GNSS变形监测是什么?主要有怎样的应用与优势?
前端