React中Canvas转Blob加入FormData首次报错二次正常问题求助
解决Canvas转Blob首次提交无效问题
问题根源在于图片加载是异步操作,首次提交时ticket图片还没加载完成就执行了drawImage和后续的toBlob,导致Canvas内容不完整,最终dataBlob可能为null,不符合FormData.append对Blob类型的要求。二次提交时图片已被浏览器缓存,加载瞬间完成,所以能正常生成Blob。
保留现有canvas.toBlob逻辑的前提下,只需确保图片加载完成后再执行Canvas绘制操作,修改后的代码如下:
<Formik validationSchema={schema} onSubmit={async (values) => { try { // 创建Canvas并等待图片加载完成 const canvas = document.createElement("canvas"); const layout = canvas.getContext("2d"); const ticket = new Image(); // 用Promise包裹图片加载,确保加载完成后再执行后续逻辑 await new Promise((resolve, reject) => { ticket.onload = resolve; ticket.onerror = reject; ticket.src = target.ticket_img; }); // 图片加载完成后设置Canvas尺寸并绘制图片 canvas.width = ticket.naturalWidth; canvas.height = ticket.naturalHeight; layout.drawImage( ticket, 0, 0, ticket.naturalWidth, ticket.naturalHeight ); // 添加宾客姓名文字 const textName = values.name; layout.rotate(4.71); layout.font = "52px Archive"; layout.fillStyle = "#faf9f6"; layout.textAlign = "center"; layout.strokeText(textName, -255, 1170); layout.fillText(textName, -255, 1170); layout.font = "52px Archive"; layout.fillStyle = "#faf9f6"; const textSurname = values.surname; layout.textAlign = "center"; layout.strokeText(textSurname, -255, 1230); layout.fillText(textSurname, -255, 1230); // 转为Blob const dataBlob = await new Promise((resolve) => canvas.toBlob((blob) => resolve(blob), "image/webp") ); // 构建FormData并提交 const formData = new FormData(); formData.append( "image", dataBlob, `${target.title}_${values.name}${values.surname}_GUEST` ); // 后续提交逻辑... } catch (err) { console.log(err); } }} > {/* 表单内容 */} </Formik>
关键改动说明:
- 新增
await new Promise包裹图片加载过程,通过ticket.onload确保图片加载完成后才继续执行 - 将原有的图片绘制、文字添加等逻辑移到图片加载完成的回调之后,保证Canvas能正确渲染完整内容
这样修改后,无论首次还是后续提交,都会等待图片加载完成后再生成Blob,避免因图片未加载导致的dataBlob无效问题。
内容的提问来源于stack exchange,提问作者Vladislav Marinov
相关产品推荐
相关产品推荐

