gopdf gopdf is a simple library for generating PDF document written in Go lang.
A minimum version of Go 1.13 is required.
Features Unicode subfont embedding. (Chinese, Japanese, Korean, etc.) Draw line, oval, rect, curve Draw image ( jpg, png ) Set image mask Password protection Font kerning Installation go get -u github.com/signintech/gopdf Print text
package main
import (
"log"
"github.com/signintech/gopdf"
)
func main() {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 })
pdf.AddPage()
err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf")
if err != nil {
log.Print(err.Error())
return
}
err = pdf.SetFont("wts11", "", 14)
if err != nil {
log.Print(err.Error())
return
}
pdf.Cell(nil, "您好")
pdf.WritePdf("hello.pdf")
}
Set text color using RGB color model pdf.SetTextColor(156, 197, 140) pdf.Cell(nil, "您好") Set text color using CMYK color model pdf.SetTextColorCMYK(0, 6, 14, 0) pdf.Cell
Image
package main
import (
"log"
"github.com/signintech/gopdf"
)
func main() {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4 })
pdf.AddPage()
var err error
err = pdf.AddTTFFont("loma", "../ttf/Loma.ttf")
if err != nil {
log.Print(err.Error())
return
}
pdf.Image("../imgs/gopher.jpg", 200, 50, nil) //print image
err = pdf.SetFont("loma", "", 14)
if err != nil {
log.Print(err.Error())
return
}
pdf.SetXY(250, 200) //move current location
pdf.Cell(nil, "gopher and gopher") //print text
pdf.WritePdf("image.pdf")
}
Links
package main
import (
"log"
"github.com/signintech/gopdf"
)
func main() {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 }) //595.28, 841.89 = A4
pdf.AddPage()
err := pdf.AddTTFFont("times", "./test/res/times.ttf")
if err != nil {
log.Print(err.Error())
return
}
err = pdf.SetFont("times", "", 14)
if err != nil {
log.Print(err.Error())
return
}
pdf.SetXY(30, 40)
pdf.Text("Link to example.com")
pdf.AddExternalLink("http://example.com/", 27.5, 28, 125, 15)
pdf.SetXY(30, 70)
pdf.Text("Link to second page")
pdf.AddInternalLink("anchor", 27.5, 58, 120, 15)
pdf.AddPage()
pdf.SetXY(30, 100)
pdf.SetAnchor("anchor")
pdf.Text("Anchor position")
pdf.WritePdf("hello.tmp.pdf")
}
Header and Footer
package main
import (
"log"
"github.com/signintech/gopdf"
)
func main() {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 }) //595.28, 841.89 = A4
err := pdf.AddTTFFont("LiberationSerif-Regular", "./test/res/LiberationSerif-Regular.ttf")
if err != nil {
log.Print(err.Error())
return
}
err = pdf.SetFont("LiberationSerif-Regular", "", 14)
if err != nil {
log.Print(err.Error())
return
}
pdf.AddHeader(func() {
pdf.SetY(5)
pdf.Cell(nil, "header")
})
pdf.AddFooter(func() {
pdf.SetY(825)
pdf.Cell(nil, "footer")
})
pdf.AddPage()
pdf.SetY(400)
pdf.Text("page 1 content")
pdf.AddPage()
pdf.SetY(400)
pdf.Text("page 2 content")
pdf.WritePdf("header-footer.tmp.pdf")
}
Draw line
pdf.SetLineWidth(2)
pdf.SetLineType("dashed")
pdf.Line(10, 30, 585, 30)
Draw oval
pdf.SetLineWidth(1)
pdf.Oval(100, 200, 500, 500)
Draw polygon
pdf.SetStrokeColor(255, 0, 0)
pdf.SetLineWidth(2)
pdf.SetFillColor(0, 255, 0)
pdf.Polygon([]gopdf.Point{{X: 10, Y: 30}, {X: 585, Y: 200}, {X: 585, Y: 250}}, "DF")
Draw rectangle with round corner
pdf.SetStrokeColor(255, 0, 0)
pdf.SetLineWidth(2)
pdf.SetFillColor(0, 255, 0)
err := pdf.Rectangle(196.6, 336.8, 398.3, 379.3, "DF", 3, 10)
if err != nil {
return err
}
Draw rectangle with round corner using CMYK color model
pdf.SetStrokeColorCMYK(88, 49, 0, 0)
pdf.SetLineWidth(2)
pdf.SetFillColorCMYK(0, 5, 89, 0)
err := pdf.Rectangle(196.6, 336.8, 398.3, 379.3, "DF", 3, 10)
if err != nil {
return err
}
Rotation text or image
pdf.SetXY(100, 100)
pdf.Rotate(270.0, 100.0, 100.0)
pdf.Text("Hello...")
pdf.RotateReset() //reset
Set transparency
Read about transparency in pdf (page 320, section 11)
// alpha - value of transparency, can be between `0` and `1`
// blendMode - default value is `/Normal` - read about [blendMode and kinds of its](https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf) `(page 325, section 11.3.5)`
transparency := Transparency{
Alpha: 0.5,
BlendModeType: "",
}
pdf.SetTransparency(transparency Transparency)
Password protection
package main
import (
"log"
"github.com/signintech/gopdf"
)
func main() {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{
PageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4
Protection: gopdf.PDFProtectionConfig{
UseProtection: true,
Permissions: gopdf.PermissionsPrint | gopdf.PermissionsCopy | gopdf.PermissionsModify,
OwnerPass: []byte("123456"),
UserPass: []byte("123456789")},
})
pdf.AddPage()
pdf.AddTTFFont("loma", "../ttf/loma.ttf")
pdf.Cell(nil,"Hi")
pdf.WritePdf("protect.pdf")
}
Import existing PDF
Import existing PDF power by package gofpdi created by @phpdave11 (thank you :smile:)
package main
import (
"github.com/signintech/gopdf"
"io"
"net/http"
"os"
)
func main() {
var err error
// Download a Font
fontUrl := "https://github.com/google/fonts/raw/master/ofl/daysone/DaysOne-Regular.ttf"
if err = DownloadFile("example-font.ttf", fontUrl); err != nil {
panic(err)
}
// Download a PDF
fileUrl := "https://tcpdf.org/files/examples/example_012.pdf"
if err = DownloadFile("example-pdf.pdf", fileUrl); err != nil {
panic(err)
}
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
pdf.AddPage()
err = pdf.AddTTFFont("daysone", "example-font.ttf")
if err != nil {
panic(err)
}
err = pdf.SetFont("daysone", "", 20)
if err != nil {
panic(err)
}
// Color the page
pdf.SetLineWidth(0.1)
pdf.SetFillColor(124, 252, 0) //setup fill color
pdf.RectFromUpperLeftWithStyle(50, 100, 400, 600, "FD")
pdf.SetFillColor(0, 0, 0)
pdf.SetXY(50, 50)
pdf.Cell(nil, "Import existing PDF into GoPDF Document")
// Import page 1
tpl1 := pdf.ImportPage("example-pdf.pdf", 1, "/MediaBox")
// Draw pdf onto page
pdf.UseImportedTemplate(tpl1, 50, 100, 400, 0)
pdf.WritePdf("example.pdf")
}
// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {
// Get the data
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// Create the file
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
// Write the body to file
_, err = io.Copy(out, resp.Body)
return err
}
Possible to set Trim-box
package main
import (
"log"
"github.com/signintech/gopdf"
)
func main() {
pdf := gopdf.GoPdf{}
mm6ToPx := 22.68
// Base trim-box
pdf.Start(gopdf.Config{
PageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4
TrimBox: gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},
})
// Page trim-box
opt := gopdf.PageOption{
PageSize: gopdf.PageSizeA4, //595.28, 841.89 = A4
TrimBox: &gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},
}
pdf.AddPageWithOption(opt)
if err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf"); err != nil {
log.Print(err.Error())
return
}
if err := pdf.SetFont("wts11", "", 14); err != nil {
log.Print(err.Error())
return
}
pdf.Cell(nil,"Hi")
pdf.WritePdf("hello.pdf")
}
visit https://github.com/oneplus1000/gopdfsample for more samples.
案例演示
func (l *GuitarPdfLogic) GuitarPdf(req *types.GuitarPdfReq, w http.ResponseWriter) (resp *types.GuitarPdfResp, err error) {
// 1. 初始化pdf参数
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
pageHeight := gopdf.PageSizeA4.H
pageWeight := gopdf.PageSizeA4.W
borderTop := 50.0
borderBottom := 50.0
// 初始化行高,列宽
rowHeight := 20.0
columnWidths := []float64{50, 50, 50, 50, 50, 50, 50, 50}
// 2.字体配置
ariblkFont := l.ut.ObjPath.GetStaticPwd([]string{"ariblk.ttf"})
err = pdf.AddTTFFont("ariblk", ariblkFont)
if err != nil {
logx.Error(err.Error())
return nil, err
}
err = pdf.SetFont("ariblk", "", 10)
if err != nil {
logx.Error(err.Error())
return nil, err
}
// 3.页眉
pdf.AddHeader(func() {
pdf.SetXY(pageWeight/2, borderTop/2)
// 画图
pdf.Image(l.ut.ObjPath.GetStaticPwd([]string{"aliyun.PNG"}), pageHeight/4, borderTop/2, &gopdf.Rect{W: 30, H: 20})
pdf.Cell(nil, "----header---")
})
// 4.页尾
pdf.AddFooter(func() {
pdf.SetXY(pageWeight/2, pageHeight-(borderBottom/2))
pdf.Cell(nil, "----footer----")
})
pdf.AddPage()
// 5.表格绘制
var rowCount int
pdf.SetY(borderTop)
for i := 0; i < 50; i++ {
// 获取当前所在位置高度
nowHeight := pdf.GetY()
// 获取下一行的高度
nextRowHeight := nowHeight + rowHeight // 假设下一行高度比当前行高度多2mm
if nextRowHeight > (pageHeight - float64(borderBottom)) {
// 如果下一行的高度超过了当前页面的剩余空间,则添加新页面
pdf.AddPage()
pdf.SetY(borderTop)
}
// 在新的一行开始
pdf.Br(rowHeight)
// 在每一列添加单元格
for _, width := range columnWidths {
// 添加单元格
pdf.CellWithOption(&gopdf.Rect{
W: width,
H: rowHeight,
}, fmt.Sprintf("%d,%d", i+1, rowCount), gopdf.CellOption{Align: gopdf.Center | gopdf.Middle})
}
}
// 写入http
n, err := pdf.WriteTo(w)
logx.Error(n)
if err != nil {
return nil, err
}
return
}