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。
疑问
- 是否有人解决过pdfMake结合日文字体在Chrome中的这类问题?
- 能否通过修复文本编码使日文可被搜索?
- 是否需要特定的字体格式设置?
- 这是否属于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
相关产品推荐
相关产品推荐

