已有 PDF 叠加

概述

gpdf 可以打开已有的 PDF 并在其上叠加新内容,而不修改原始数据。这使用了增量更新技术 — 新对象被追加到原始 PDF 字节之后。

常见用例:

  • 添加水印("DRAFT"、"CONFIDENTIAL")
  • 插入页码
  • 盖章审批标记和日期
  • 为已有文档添加页眉/页脚

打开已有 PDF

import gpdf "github.com/gpdf-dev/gpdf"

// Read existing PDF bytes (from file, HTTP response, database, etc.)
pdfBytes, _ := os.ReadFile("input.pdf")

doc, err := gpdf.Open(pdfBytes)
if err != nil {
    log.Fatal(err)
}

你可以传递与 NewDocument 相同的选项 — 字体、默认字体等:

doc, err := gpdf.Open(pdfBytes,
    gpdf.WithFont("NotoSans", fontData),
    gpdf.WithDefaultFont("NotoSans", 12),
)

在单个页面上叠加

使用 Overlay(pageIndex, fn) 在指定页面上添加内容(从 0 开始索引):

doc.Overlay(0, func(p *template.PageBuilder) {
    p.Absolute(document.Mm(40), document.Mm(120), func(c *template.ColBuilder) {
        c.Text("DRAFT",
            template.FontSize(72),
            template.TextColor(pdf.Gray(0.85)),
        )
    })
})

PageBuilder 支持与创建新页面时相同的 API — AutoRowAbsoluteRow 等。

在每一页上叠加

使用 EachPage(fn) 遍历所有页面:

count, _ := doc.PageCount()

doc.EachPage(func(pageIndex int, p *template.PageBuilder) {
    p.Absolute(document.Mm(170), document.Mm(285), func(c *template.ColBuilder) {
        c.Text(fmt.Sprintf("%d / %d", pageIndex+1, count),
            template.FontSize(10),
            template.AlignRight(),
        )
    }, template.AbsoluteWidth(document.Mm(20)))
})

保存结果

result, err := doc.Save()
if err != nil {
    log.Fatal(err)
}
os.WriteFile("output.pdf", result, 0644)

原始 PDF 内容得以保留 — Save() 将叠加数据追加到原始字节之后。

完整示例:水印 + 页码

pdfBytes, _ := os.ReadFile("report.pdf")

doc, err := gpdf.Open(pdfBytes)
if err != nil {
    log.Fatal(err)
}

count, _ := doc.PageCount()

doc.EachPage(func(i int, p *template.PageBuilder) {
    // Watermark
    p.Absolute(document.Mm(40), document.Mm(140), func(c *template.ColBuilder) {
        c.Text("CONFIDENTIAL",
            template.FontSize(60),
            template.TextColor(pdf.Color{R: 0.9, G: 0.9, B: 0.9, A: 1, Space: pdf.ColorSpaceRGB}),
        )
    })

    // Page number (bottom-right)
    p.Absolute(document.Mm(170), document.Mm(285), func(c *template.ColBuilder) {
        c.Text(fmt.Sprintf("%d / %d", i+1, count),
            template.FontSize(10),
            template.AlignRight(),
        )
    }, template.AbsoluteWidth(document.Mm(20)))
})

result, _ := doc.Save()
os.WriteFile("report_stamped.pdf", result, 0644)

API 参考

方法说明
gpdf.Open(data, opts...)打开已有 PDF 进行修改
doc.PageCount()获取页面数量
doc.Overlay(pageIndex, fn)在指定页面上添加内容(从 0 开始)
doc.EachPage(fn)在每一页上添加内容
doc.Save()返回修改后的 PDF 字节

下一步