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

为何readAsDataURL对PDF不同页面返回相同DataURL字符串?

PDF转PNG时页面DataURL重复的问题分析

转换代码

export async function convertFromPdf(f: any) {
  const pdfjsLib = require("pdfjs-dist/webpack");

  const pdf = await pdfjsLib.getDocument(f).promise;
  const pdfPages = await toImageData(pdf);

  const pages = await Promise.all(
    pdfPages.map(async (x) => {
      if (!x) return null;

      const canvas = document.createElement("canvas");
      canvas.width = x.width;
      canvas.height = x.height;
      const ctx = canvas.getContext("2d");
      ctx?.putImageData(x, 0, 0);

      const blob = await new Promise<Blob | null>((resolve) => {
        canvas.toBlob((blob) => resolve(blob));
      });

      if (!blob) return null;

      const reader = new FileReader();
      reader.readAsDataURL(blob);

      return await new Promise<string>((resolve) => {
        reader.onloadend = () => resolve(reader.result as string);
      });
    })
  );

  return pages.filter((x) => x !== null) as string[];
}

async function toImageData(pdf: any) {
  const pdfPages = [];
  for (let i = 1; i <= pdf.numPages; i++) {
    const page = await pdf.getPage(i);
    const viewport = page.getViewport({ scale: 1.5 });
    const canvas = document.createElement("canvas");
    canvas.width = viewport.width;
    canvas.height = viewport.height;
    const ctx = canvas.getContext("2d");
    const renderContext = { canvasContext: ctx, viewport: viewport };

    await page.render(renderContext).promise;
    pdfPages.push(ctx?.getImageData(0, 0, canvas.width, canvas.height));
  }
  return pdfPages;
}

问题描述

我使用上述函数将PDF转换为PNG图片,但在某些情况下,reader.readAsDataURL(blob)会对PDF的两个不同页面返回完全相同的字符串。这会导致后续UI交互出现问题,比如选择操作会同时选中两个页面,因为它们的URL一致,请问该问题的成因是什么?

成因分析

  • 页面渲染异常导致ImageData重复:在toImageData的循环渲染过程中,若某一页渲染失败(比如PDF页面损坏、资源加载异常),或者viewport计算错误,会生成空白或重复的ImageData。这些重复的ImageData转成Blob后,对应的DataURL自然完全一致。
  • 空白页面或内容完全重合:如果PDF本身存在两个空白页面,或者渲染后的页面内容完全相同(比如模板页、重复的占位页),canvas.toBlob()生成的Blob内容毫无差异,readAsDataURL输出的Base64字符串也会一模一样。
  • PDF.js渲染的缓存或竞态问题:PDF.js内部可能存在渲染缓存,当连续渲染结构相似的页面时,可能复用了之前的渲染结果;或者循环中异步渲染的时序出现问题,导致后一页覆盖了前一页的canvas内容,最终生成重复的ImageData。
  • FileReader无差异化处理:readAsDataURL的输出完全依赖输入Blob的内容,只要Blob的二进制数据一致,不管来源是哪个页面,生成的DataURL必然相同。这是该API的特性,不是bug,但会暴露上游渲染环节的问题。

内容的提问来源于stack exchange,提问作者Owenn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:04:59