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

不依赖第三方库手动创建含表格与图片的PDF发票技术问询

手动构建含文本、表格、图片的PDF发票(原始对象实现)

核心思路

PDF的所有内容都是通过内容流(Content Stream) + 对应资源对象(字体、图片等)实现的:表格本质是画线条+单元格文本定位,图片是嵌入XObject资源后调用绘制。


1. 表格实现(原始对象版)

表格不需要特殊对象,用路径指令画边框,再把文本定位到单元格内即可。以下是简化的发票表格对象示例:

表格资源与内容流

先定义基础字体资源,再在内容流里完成线条绘制和文本写入:

% 字体资源对象(对象2)
2 0 obj
<<
  /Type /Font
  /Subtype /Type1
  /BaseFont /Helvetica
  /Encoding /WinAnsiEncoding
>>
endobj

% 页面内容流对象(对象3)
3 0 obj
<< /Length 400 >>
stream
% 设置字体和字号
BT
/Helvetica 12 Tf
% 画表格外框:左上角(50,700),右下角(550,500)
50 700 m
550 700 l
550 500 l
50 500 l
50 700 l
S
% 画列分隔线:3列,每列宽度166
216 700 m
216 500 l
S
382 700 m
382 500 l
S
% 画行分隔线:3行,每行高度66
50 634 m
550 634 l
S
50 568 m
550 568 l
S
% 写入表头文本
55 685 Td (商品名称) Tj
221 685 Td (数量) Tj
387 685 Td (金额) Tj
% 写入第一行数据
55 619 Td (笔记本电脑) Tj
221 619 Td (1) Tj
387 619 Td (5999) Tj
ET
endstream
endobj

关键逻辑说明

  • m = 移动画笔到目标坐标,l = 从当前点画直线到目标点,S = 描边路径(画出线条)
  • BT/ET 包裹文本操作块,Td 移动文本光标到指定坐标,Tj 输出文本内容
  • PDF坐标以页面左下角为原点,单位为PDF点(1点=1/72英寸)

2. 图片嵌入与绘制(原始对象版)

图片需要定义为XObject资源,再在内容流里调用绘制。以下是嵌入200x100尺寸RGB图片的示例:

图片对象与内容流

% 图片XObject对象(对象4)
4 0 obj
<<
  /Type /XObject
  /Subtype /Image
  /Width 200
  /Height 100
  /ColorSpace /DeviceRGB
  /BitsPerComponent 8
  /Filter /FlateDecode % 用Flate压缩,测试时可直接去掉用原始RGB数据
  /Length 120000 % 需匹配实际压缩后的数据长度
>>
stream
% 此处放入压缩后的RGB图像二进制数据:每个像素3字节(R,G,B),共200*100*3=60000字节,压缩后长度需对应上面的/Length值
[实际压缩图像数据]
endstream
endobj

% 在页面内容流(对象3的stream)中添加图片绘制指令
q % 保存当前画布状态
200 0 0 100 50 750 cm % 设置缩放与位置:宽200、高100,左下角坐标(50,750)
/Img1 Do % 调用图片XObject资源
Q % 恢复画布状态

关键逻辑说明

  • 需要在页面字典的/Resources中添加图片引用:/XObject << /Img1 4 0 R >>
  • cm 是矩阵变换指令,格式为[X轴缩放 X倾斜 Y倾斜 Y轴缩放 X偏移 Y偏移],用于控制图片大小与位置
  • 测试小图时可去掉/Filter /FlateDecode,直接放入原始60000字节RGB数据,更直观

3. 完整发票PDF结构框架

将所有对象组合,完整PDF文件结构如下(简化版):

%PDF-1.7
1 0 obj
<<
  /Type /Catalog
  /Pages 5 0 R
>>
endobj

% 字体资源对象(对象2)
2 0 obj
<<
  /Type /Font
  /Subtype /Type1
  /BaseFont /Helvetica
  /Encoding /WinAnsiEncoding
>>
endobj

% 页面内容流对象(对象3)
3 0 obj
<< /Length 800 >>
stream
% 绘制发票logo图片
q
200 0 0 100 50 750 cm
/Img1 Do
Q
% 写入发票标题
BT
/Helvetica 16 Tf
300 720 Td (XX公司发票) Tj
ET
% 绘制表格与内容(前面表格的内容流代码)
BT
/Helvetica 12 Tf
50 700 m
550 700 l
550 500 l
50 500 l
50 700 l
S
% ... 剩余表格线条与文本指令
ET
endstream
endobj

% 图片XObject对象(对象4)
4 0 obj
<<
  /Type /XObject
  /Subtype /Image
  /Width 200
  /Height 100
  /ColorSpace /DeviceRGB
  /BitsPerComponent 8
  /Filter /FlateDecode
  /Length [实际数据长度]
>>
stream
[压缩图像数据]
endstream
endobj

% 页面集合字典(对象5)
5 0 obj
<<
  /Type /Pages
  /Kids [6 0 R]
  /Count 1
>>
endobj

% 页面对象(对象6)
6 0 obj
<<
  /Type /Page
  /Parent 5 0 R
  /MediaBox [0 0 612 792] % A4页面尺寸
  /Resources <<
    /Font << /F1 2 0 R >>
    /XObject << /Img1 4 0 R >>
  >>
  /Contents 3 0 R
>>
endobj

% 交叉引用表
xref
0 7
0000000000 65535 f 
0000000009 00000 n 
0000000079 00000 n 
0000000173 00000 n 
0000000500 00000 n 
0000000800 00000 n 
0000000900 00000 n 

% Trailer
trailer
<<
  /Size 7
  /Root 1 0 R
>>
startxref
1000
%%EOF

注意事项

  • 所有对象编号需与交叉引用表一一对应,交叉引用中的字节偏移量需准确(可保存后用文本编辑器查看字节数调整)
  • 文本坐标需自行计算,确保在单元格内对齐
  • 若用FlateDecode压缩图片,可借助gzip工具压缩原始RGB数据后再放入stream

内容的提问来源于stack exchange,提问作者Sandhya Yegireddi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:20:35