在jsPDF中添加古吉拉特语字体遇atob编码错误的技术求助
解决jsPDF中atob编码错误并实现古吉拉特语字体渲染
错误根源
你遇到的执行'Window'上的'atob'失败:待解码字符串编码不正确异常,核心原因是:doc.addFileToVFS()方法的第二个参数需要传入字体文件的base64编码字符串,但你传入的是字体文件的相对路径./assets/fonts/Aakar.ttf,导致atob尝试解码非base64格式的字符串,直接抛出异常。
分步解决方案
1. 将古吉拉特语字体转为Base64编码
可以通过前端代码动态读取字体文件并转换,避免手动复制base64的繁琐:
async getFontBase64(url: string): Promise<string> { const response = await fetch(url); const blob = await response.blob(); return new Promise((resolve) => { const reader = new FileReader(); reader.onloadend = () => resolve((reader.result as string).split(',')[1]); // 移除data URI前缀 reader.readAsDataURL(blob); }); }
2. 修正jsPDF字体加载逻辑
替换原错误的路径传入方式,改用base64字符串加载字体:
// 示例:加载Aakar字体 const aakarFontBase64 = await this.getFontBase64('./assets/fonts/Aakar.ttf'); const doc = new jsPDF(); // 先将字体添加到虚拟文件系统 doc.addFileToVFS('Aakar.ttf', aakarFontBase64); // 注册字体 doc.addFont('Aakar.ttf', 'Aakar', 'normal'); // 全局设置字体 doc.setFont('Aakar', 'normal');
3. 优化重复调用doc.html()的问题
原代码中两次调用doc.html()会导致PDF生成逻辑混乱,合并为一次回调同时处理保存和上传:
async convetToPDF(type: any) { let pdfTable: HTMLElement | undefined; if (type === 1) { pdfTable = this.pdfTable.nativeElement; const aakarFontBase64 = await this.getFontBase64('./assets/fonts/Aakar.ttf'); const doc = new jsPDF(); doc.addFileToVFS('Aakar.ttf', aakarFontBase64); doc.addFont('Aakar.ttf', 'Aakar', 'normal'); doc.setFont('Aakar', 'normal'); doc.html(pdfTable, { callback: (generatedDoc) => { // 保存PDF generatedDoc.save('test.pdf'); // 处理上传逻辑 const pdfBlob = generatedDoc.output('blob'); this.selectedItemPrintData = undefined; this.itemIngredientPrintData = undefined; const formData = new FormData(); formData.append('file', pdfBlob, 'abc.pdf'); // 直接传入Blob对象 formData.append('orderId', this.orderId); this.helper.http_post_method_requester( this.helper.POST_METHOD.SENDPDF_SELECTEDITEM, formData, true, true, true, true, (res: any) => { res.Success ? this.toster.success(res.message) : this.toster.error(res.message); } ); }, margin: [0, 0], html2canvas: { scale: 2, useCORS: true }, // 提高scale保证清晰度 x: 5, y: 5, }); } else { for (const x of this.finalMultiIngredients) { const divId = x.agencyId; pdfTable = document.getElementById(divId); if (!pdfTable) continue; // 避免空元素报错 const avantikaFontBase64 = await this.getFontBase64('./assets/fonts/Avantika-normal.ttf'); const doc = new jsPDF(); doc.addFileToVFS('Avantika-normal.ttf', avantikaFontBase64); doc.addFont('Avantika-normal.ttf', 'Avantika', 'normal'); doc.setFont('Avantika', 'normal'); doc.html(pdfTable, { callback: (generatedDoc) => { generatedDoc.save(`IngredientList_${divId}.pdf`); const pdfBlob = generatedDoc.output('blob'); const formData = new FormData(); formData.append('file', pdfBlob, `IngredientList_${divId}.pdf`); formData.append('agencyId', x.agencyId); this.helper.http_post_method_requester( this.helper.POST_METHOD.SEND_INGREDIENT_PDF, formData, true, true, true, true, (res: any) => { res.Success ? this.toster.success(res.message) : this.toster.error(res.message); } ); }, margin: [0, 0], html2canvas: { scale: 2, useCORS: true }, x: 5, y: 5, }); } } }
4. 确保古吉拉特语渲染正常的额外配置
- 预先在HTML页面加载字体,避免html2canvas截图时字体未加载完成:
@font-face { font-family: 'Aakar'; src: url('./assets/fonts/Aakar.ttf') format('truetype'); font-weight: normal; font-style: normal; } @font-face { font-family: 'Avantika'; src: url('./assets/fonts/Avantika-normal.ttf') format('truetype'); font-weight: normal; font-style: normal; } /* 给PDF目标元素设置字体 */ .pdf-table { font-family: 'Aakar', 'Avantika', sans-serif; }
- 确保使用的字体支持完整的古吉拉特语Unicode字符集,避免复杂字形/连字显示异常。
内容的提问来源于stack exchange,提问作者J D
相关产品推荐
相关产品推荐

