前端 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 之前
相关推荐
zxna2 小时前
前端直连oss分片上传文件,断点续传
前端
Southern Wind2 小时前
Vue 3 + Socket.io 实时聊天项目完整开发文档
前端·javascript·vue.js
甄心爱学习2 小时前
【项目实训(个人4)】
前端·vue.js·python
轮子大叔2 小时前
HTML入门
前端·html
skilllite作者2 小时前
SkillLite 技术演进笔记:Workspace、沙箱与进化
java·开发语言·前端·笔记·安全·agentskills
qq_419854052 小时前
clip-path绘制倾斜角裁剪的矩形占比条;基于svg实现仪表盘弧线占比图。
前端·javascript·vue.js
m0_738120722 小时前
渗透基础知识ctfshow——Web应用安全与防护(完结:第八章)
前端·python·sql·安全·web安全·网络安全
克里斯蒂亚诺更新2 小时前
uniapp适配H5和Android-apk实现获取当前位置经纬度并调用接口
android·前端·uni-app
宁&沉沦2 小时前
前端开发专用的 Cursor 四大模式「快捷切换 + 指令模板」,直接复制就能用,覆盖 90% 日常场景
前端·编辑器