You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:45:06