uni-app 含跨域资源的canvas调用uni.canvasToTempFilePath在h5环境报错

uni-app 含跨域资源的canvas调用uni.canvasToTempFilePath在h5环境报错

示例代码:

<canvas  
    canvas-id="canvasid"  
    :style="{width:100%, height: 100%}"  
/>
let ctx = uni.createCanvasContext('canvasid', this);  
ctx.drawImage(imgPath, 0, 0, 500, 500, 0, 0);  

setTimeout(() => {  
    uni.canvasToTempFilePath({  
        canvasId: 'canvasid',  
        success: (res) => {  
            console.log('res.tempFilePath', res.tempFilePath)  
        },  
        fail: (err) => {  
            console.log('uni.canvasToTempFilePath海报生成错误', err);  
        }  
    }, this);  
}, 3000);

操作步骤:

  1. 设置imgPath为非跨域图片资源,成功输出canvas的base64
  2. 设置imgPath为跨域图片资源(服务端已设置白名单),IOS报错“canvasToTempFilePath:fail SecurityError:The operation is in secure”,安卓不报错
  3. 修改node_modules/@dcloudio目录下的代码,在所有为img标签设置src属性的代码前一行都添加了类似以下语句(因为不确定真正是哪一处生效,干脆全部设置):
    image.setAttribute('crossOrigin', 'anonymous')
    
    修改之后运行,ios和安卓都不报错。

预期结果:

H5在ios设备运行正常返回canvas的base64

实际结果:

H5在ios设备运行未返回canvas的base64,报错:

canvasToTempFilePath:fail SecurityError:The operation is in secure

bug描述:

含跨域资源的canvas调用uni.canvasToTempFilePath在h5环境报错:

canvasToTempFilePath:fail SecurityError:The operation is in secure

为了验证这个问题,我尝试直接修改node_modules/@dcloudio目录下的代码,在所有为img标签设置src属性的代码前一行都添加了类似以下语句(因为不确定真正是哪一处生效,干脆全部设置):

image.setAttribute('crossOrigin', 'anonymous')

运行之后ios设备运行H5就正常了。


更多关于uni-app 含跨域资源的canvas调用uni.canvasToTempFilePath在h5环境报错的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

请问修改的是那部分的代码

更多关于uni-app 含跨域资源的canvas调用uni.canvasToTempFilePath在h5环境报错的实战教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个典型的H5跨域Canvas安全问题。在iOS的WebView中,当Canvas包含跨域图片资源时,直接调用toDataURL或相关API会触发安全限制。

解决方案要点:

  1. 确保跨域图片服务器正确配置CORS头:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
  1. 在代码中显式设置crossOrigin属性:
const img = new Image()
img.crossOrigin = 'anonymous'
img.src = imgPath
  1. 对于uni-app的H5端,推荐使用uni.downloadFile下载图片到本地后再绘制:
uni.downloadFile({
  url: imgPath,
  success: (res) => {
    ctx.drawImage(res.tempFilePath, 0, 0)
  }
})
回到顶部