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

Next.js中pdfMake生成PDF日文在Chrome无法搜索复制求助

问题描述

我在Next.js项目中使用pdfMake工具生成包含日文的PDF文件,采用NotoSansJP字体。字体通过fetch接口获取后转Base64编码,加载到虚拟文件系统(vfs)中,生成的PDF在所有浏览器都能正常显示日文内容,但存在以下问题:

  • Chrome浏览器中,日文文本无法被搜索,复制时还会出现乱码(例如:89:;, rst}~);
  • Safari和Edge浏览器中,文本可正常复制和搜索;
  • 特殊情况:仅当设置bold: true时,“支援等記録”这串文本可在Chrome中被搜索。

已尝试的解决措施

  • 嵌入NotoSansJP字体的.ttf和.otf版本;
  • 在defaultStyle和单个文本层级分别设置字体;
  • 验证字体已正确获取、Base64编码并加载至vfs。

疑问

  1. 是否有人解决过pdfMake结合日文字体在Chrome中的这类问题?
  2. 能否通过修复文本编码使日文可被搜索?
  3. 是否需要特定的字体格式设置?
  4. 这是否属于Chrome PDF渲染器的限制?

相关代码

let isPdfMakeReady = false;

async function fetchFontBase64(url: string): Promise<string> {
  const res = await fetch(url);
  const blob = await res.blob();

  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      const result = reader.result as string;
      resolve(result.split(',')[1]); // remove "data:application/x-font-otf;base64,"
    };
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

export async function initFonts() {
  if (isPdfMakeReady || typeof window === 'undefined') return pdfMake;

  const [regular, bold] = await Promise.all([
    fetchFontBase64('/fonts/NotoSansJP-Regular.ttf'),
    fetchFontBase64('/fonts/NotoSansJP-Bold.ttf'),
  ]);

  pdfMake.vfs = {
    'NotoSansJP-Regular.otf': regular,
    'NotoSansJP-Bold.otf': bold,
  };

  pdfMake.fonts = {
    NotoSansJP: {
      normal: 'NotoSansJP-Regular.otf',
      bold: 'NotoSansJP-Bold.otf',
      italics: 'NotoSansJP-Regular.otf',
      bolditalics: 'NotoSansJP-Bold.otf',
    }
  };

  isPdfMakeReady = true;
}

initFonts();

let definition: TDocumentDefinitions = {
  pageSize: "A4",
  pageOrientation: pageOrientation,
  pageMargins: pageOrientation === "portrait" ? [0, 20, 0, 90] : [30, 20, 30, 90],
  content: [
    {
      text: '支援等記録', style: {
        font: "NotoSansJP",
        fontSize: 18,
        bold: false,
      }
    },
    {
      marginLeft: 20,
      marginRight: 28,
      columns: [
        {
          width: "*",
          stack: [
            {
              table: {
                widths: ["*", "*", '*'],
                body: [
                  [
                    { text: groupHome.name, bold: true },
                    "",
                    { text: '', alignment: "right", bold: true }
                  ],
                  [
                    { text: `${customer.name} 様`, style: "text" },
                    "",
                    { text: "", alignment: "right" }
                  ]
                ]
              },
              layout: 'noBorders'
            },
            {
              marginTop: 10,
              table: {
                widths: [100, 100],
                body: [
                  ['日付', getDisplayDate(date)],
                  ['水分合計量', getWaterAmountTotal(dailyRecordGroup.records).toString() + "ml"]
                ]
              },
            },
          ]
        },
        {
          width: 50,
          table: {
            widths: [50],
            heights: [10, 50],
            body: [
              [{ text: '利用者確認印', alignment: "center" }],
              [(stampSetting && stampSetting[RECORD_PDF_STAMP_TYPES.CUSTOMER as keyof RecordPdfStampSetting] && stampImage) ? {
                image: stampImage,
                width: 50,
                height: 50
              } : ""]
            ]
          },
        }
      ]
    }
  ],
  footer: function (currentPage, pageCount) {
    return [
      {
        text: `${currentPage.toString()} / ${pageCount}`,
        marginLeft: 560,
        marginTop: 60
      }
    ];
  },
  defaultStyle: {
    font: 'NotoSansJP',
    fontSize: 8,
    lineHeight: 0.9
  },
  styles: {
    title: {
      fontSize: 18,
      bold: true,
      alignment: "center",
      marginBottom: 20
    },
    subheader: {
      fontSize: 12,
      bold: true,
      margin: [0, 10, 0, 5]
    },
    text: {
      fontSize: 8,
      bold: false,
    },
    tableExample: {
      margin: [0, 5, 0, 15]
    }
  },
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:07:33