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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 09:52:48