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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 12:25:22