如何用Vanilla JS生成PDF:解决URL自动关闭、获取Base64等问题
纯Vanilla JS生成PDF(无第三方库)
为什么你之前的方法无效
你直接用new File()把HTML字符串存为PDF文件是错误的——PDF有自己的二进制文件格式规范,不是简单的文本/HTML内容。就算你设置了type: 'application/pdf',文件本质还是HTML文本,PDF阅读器无法识别这种无效内容,所以会出现打开后自动关闭的问题。
手动构造有效PDF的基础方法
要生成真正可识别的PDF,需要手动构造符合PDF规范的内容。下面是一个生成包含简单文本的PDF示例:
// 构造符合PDF规范的内容 const pdfContent = `%PDF-1.7 1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj 2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj 3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >> endobj 4 0 obj << /Length 44 >> stream BT /F1 24 Tf 100 700 Td (Hello, Vanilla JS PDF!) Tj ET endstream endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> endobj xref 0 6 0000000000 65535 f 0000000010 00000 n 0000000079 00000 n 0000000173 00000 n 0000000301 00000 n 0000000425 00000 n trailer << /Size 6 /Root 1 0 R >> startxref 562 %%EOF`; // 将内容转为Blob(File继承自Blob,这里用Blob更灵活) const pdfBlob = new Blob([pdfContent], { type: 'application/pdf' }); // 方法1:生成可打开的URL(内容有效,不会自动关闭) const pdfUrl = URL.createObjectURL(pdfBlob); window.open(pdfUrl); // 使用完后建议释放URL,避免内存泄漏 // setTimeout(() => URL.revokeObjectURL(pdfUrl), 10000); // 方法2:直接下载PDF const a = document.createElement('a'); a.href = pdfUrl; a.download = 'vanilla-js.pdf'; a.click();
向PDF中添加数据的思路
要添加更多内容,需要修改PDF的内容流(示例中第4个对象的stream部分),常见操作示例:
- 添加多行文本:在内容流中添加多个
Td(设置文本位置)和Tj(绘制文本)指令 - 调整字体大小:修改
24 Tf中的数字(如改为18) - 换行:用
T*指令或手动调整Y轴坐标
示例:添加多行文本的PDF内容
// 自定义内容流 const contentStream = `BT /F1 24 Tf 100 700 Td (第一行文本) Tj 100 670 Td (第二行文本) Tj 100 640 Td (自定义动态内容) Tj ET`; // 重新构造完整PDF内容(注意更新内容流的Length和startxref位置) const updatedPdfContent = `%PDF-1.7 1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj 2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj 3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >> endobj 4 0 obj << /Length ${contentStream.length} >> stream ${contentStream} endstream endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> endobj xref 0 6 0000000000 65535 f 0000000010 00000 n 0000000079 00000 n 0000000173 00000 n 0000000301 00000 n 0000000425 00000 n trailer << /Size 6 /Root 1 0 R >> startxref 620 %%EOF`;
注意事项
- PDF格式规范复杂,手动构造仅适合简单文本需求,复杂排版(图片、表格、样式)需要深入理解PDF规范
- 交叉引用表中的字节偏移必须准确,否则PDF阅读器会报错;内容修改后需重新计算每个对象的起始字节位置
- PDF中的字符串需用括号包裹,特殊字符(如括号)要转义为
\\(或\\)
内容的提问来源于stack exchange,提问作者Web Host
相关产品推荐
相关产品推荐

