ceTe.DynamicPDF.HtmlConverter生成的PDF字节数组在Angular中使用ATOB解码时触发InvalidCharacterError的问题求助
解决Angular中atob解码PDF字节数组时的InvalidCharacterError问题
我之前帮朋友解决过几乎一模一样的问题,这个错误本质上是因为你前端拿到的内容并不是atob能处理的标准Base64字符串,咱们一步步来拆解原因和解决方案:
问题根源
atob()函数只能解码经过Base64编码的ASCII字符串,但如果服务器直接把PDF字节数组原封不动地发送,在HTTP传输过程中,二进制数据会被当成普通文本处理,导致一些不可打印的二进制字符被转义、损坏,最终前端拿到的字符串不符合Base64编码规范,自然触发解码错误。
解决方案
第一步:修改服务器端,将PDF字节数组转为Base64字符串发送
在生成PDF字节数组后,不要直接返回原始字节,而是先把它转换成Base64编码的字符串。以C#为例(因为你用的是ceTe的.NET包):
// 生成PDF字节数组 byte[] pdfBytes = Converter.Convert("your-html-content"); // 转为Base64字符串 string base64Pdf = Convert.ToBase64String(pdfBytes); // 返回这个字符串给前端(确保响应的Content-Type设为text/plain或application/json) return Ok(base64Pdf);
第二步:前端Angular正确处理Base64字符串
拿到Base64字符串后,用atob解码成二进制字符串,再转成Uint8Array,最后生成Blob用于下载或预览:
import { HttpClient } from '@angular/common/http'; import { Component } from '@angular/core'; @Component({ selector: 'app-pdf-handler', templateUrl: './pdf-handler.component.html' }) export class PdfHandlerComponent { constructor(private http: HttpClient) {} downloadPdf() { this.http.get('/api/your-pdf-endpoint', { responseType: 'text' }).subscribe({ next: (base64String) => { try { // 解码Base64为二进制字符串 const binaryString = atob(base64String); // 转换为Uint8Array const uint8Array = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { uint8Array[i] = binaryString.charCodeAt(i); } // 创建PDF Blob const pdfBlob = new Blob([uint8Array], { type: 'application/pdf' }); // 触发下载 const url = window.URL.createObjectURL(pdfBlob); const link = document.createElement('a'); link.href = url; link.download = 'generated-document.pdf'; link.click(); // 释放URL对象 window.URL.revokeObjectURL(url); } catch (error) { console.error('PDF解码失败:', error); } }, error: (err) => { console.error('获取PDF失败:', err); } }); } }
备选方案:直接传输ArrayBuffer(无需Base64)
如果不想用Base64转码,也可以让服务器直接返回二进制数据,前端请求时指定responseType: 'arraybuffer',这样完全绕开atob的问题:
downloadPdf() { this.http.get('/api/your-pdf-endpoint', { responseType: 'arraybuffer' }).subscribe({ next: (arrayBuffer) => { const pdfBlob = new Blob([arrayBuffer], { type: 'application/pdf' }); // 后续下载逻辑和上面一致 const url = window.URL.createObjectURL(pdfBlob); const link = document.createElement('a'); link.href = url; link.download = 'generated-document.pdf'; link.click(); window.URL.revokeObjectURL(url); }, error: (err) => { console.error('获取PDF失败:', err); } }); }
这种方式更高效,因为省去了Base64的编解码开销,适合大文件场景。
关键检查点
- 确保服务器返回的响应头
Content-Type正确:返回Base64时用text/plain,返回二进制时用application/pdf。 - 如果用Base64,确认服务器没有在字符串中添加额外的换行、空格等字符(有些框架会自动格式化长Base64字符串,这会导致
atob解码失败)。
内容的提问来源于stack exchange,提问作者Alex Sandor
相关产品推荐
相关产品推荐

