【开发问题】使用canvas的图片跨域问题

428 阅读1分钟

问题介绍

使用html2canvas下载dom元素内容为图片,因为浏览器对canvas的安全策略,图片跨域问题,导致canvastoDataURL错误。

解决方案

步骤一: 配置html2canvas允许跨域

export function downHtml2canvas(el, name = '未命名') {
  html2canvas(el, {
    allowTaint: false,
    useCORS: true, //允许跨域
  }).then(function(canvas) {
    const src = canvas.toDataURL('image/png', 1)
    const image = new Image()
    image.src = src
    image.crossOrigin = 'Anonymous'
    
    const url = image.src.replace(/^data:image\/[^;]/, 'data:application/octet-stream') // 输出类型
    const a = document.createElement('a') // 随便创建一个元素
    a.download = `${name}.png` // 设置下载的文件名,默认是'未命名'
    a.href = url
    document.body.appendChild(a)
    a.click()
    a.remove() // 下载之后把创建的元素删除
  })
}
注释如下:
  • allowTaint: false, useCORS: true,: html2canvas允许跨域的配置项
  • application/octet-stream
    • 遇到content-type为application/octet-stream的文件时,浏览器会直接把它下载下来。
    • 这个类型一般会配合另一个响应头Content-Disposition,该响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。
Content-Disposition: inline 
Content-Disposition: attachment 
Content-Disposition: attachment; filename="filename.jpg"

步骤二: 服务端允许图片跨域

截屏2024-04-03 上午10.49.49.png

步骤三: 不支持crossOrigin的机型

有些手机,比如某果或者部分浏览器不支持crossOrigin

axios.get(url, {
    responseType: 'blob'
}).then(function(res){

    const image = new Image()
    image.src = URL.createObjectURL(res.data)
    image.crossOrigin = 'Anonymous'
    
});
  • 先异步请求图片资源,设置响应类型为responseType为blob;
  • 再使用URL.createObjectURL将blob转换为可用blob:url。