Next.js 项目中 html-to-image 重复下载相同内容问题排查与解决
Next.js 项目使用
html-to-image 库转换下载异常问题 问题背景
我在 Next.js 项目中使用 html-to-image 实现页面 div 转 PNG 下载功能,业务代码如下:
import Image from "next/image"; import {toPng} from 'html-to-image' const divReferenceA = useRef(null); const divReferenceB = useRef(null); const [type, setType] = useState(true) const convertDivToPng = async div => { const data = await toPng(div, { cacheBust: true, canvasWidth: 842, canvasHeight: 595, }); return data; }; const handleDownloadA = async e => { try { const data = await convertDivToPng(divReferenceA.current); if (data) { const link = document.createElement("a"); link.href = data; link.download = "Image A.png"; link.click(); } } catch (e) { console.log(e, "ini error sertifikat"); } }; const handleDownloadB = async e => { try { const data = await convertDivToPng(divReferenceB.current); if (data) { const link = document.createElement("a"); link.href = data; link.download = "Image B.png"; link.click(); } } catch (e) { console.log(e, "ini errornya"); } }; return ( <div ref={divReferenceA}> {... content with <Image /> from next-image }</div> <button onClick={e => handleDownloadA(e)}> Download </button> {type == true ? ( <div className="position-relative p-0 d-flex" ref={divReferenceB}> {... content with <Image /> from next-image but different image from refA }</div> <button onClick={e => handleDownloadB(e)}> Download </button> ) : <div> </div>
问题表现
页面加载完成后首次点击 divReferenceA 对应的下载按钮,可以正常转换并下载对应 div 的完整内容;但后续点击 divReferenceB 的下载按钮,下载的仍然是 divReferenceA 的内容,打印 divReferenceB.current 可确认引用指向完全符合预期。
如果重新加载页面后先点击 divReferenceB 的下载按钮,可以正常下载 divReferenceB 的完整内容,后续再点击 divReferenceA 的下载按钮,下载的又会变成 divReferenceB 的内容。初步推测首次下载生成的 dataURL 会被持续复用,除非刷新页面,但暂未定位到具体原因。
对照测试
为了排查问题,新增了一个仅包含纯文本的测试 div 及对应下载逻辑,代码如下:
const testRef = useRef(null) const handleDownloadTest = async e => { try { const data = await convertDivToPng(testRef.current); if (data) { const link = document.createElement("a"); link.href = data; link.download = "Image B.png"; link.click(); } } catch (e) { console.log(e, "ini errornya"); } }; <div ref={testRef}> <div>a</div> <div>a</div> <div>a</div> </div>
测试功能完全正常,没有出现上述重复下载的问题,因此初步怀疑异常和 Next/Image 组件有关。
问题解决方案
最终定位到问题根源是后端环境未正确配置CORS规则,通过直接请求S3存储桶的图片接口时得到了CORS相关报错,测试代码如下:
const data = await axios.get('s3-bucket-api') if(data){ console.log(data) }
调整后端S3存储桶的CORS配置后问题完全解决。
内容的提问来源于stack exchange,提问作者Ahmad Firaz
相关产品推荐
相关产品推荐

