原由
我发现在工具中有需要转换txt文件到pdf的需求
抱着学习的态度就找了go语言的pdf库试试
以下是我的成果
包括转换文本文件到pdf文件
转换图片文件到pdf文件
和 pdf文件切分
以方便分批次打印
以下尽量把内容写在注释里以方便阅读
转换文本文件到pdf文件
- 按字典顺序命名要合并转换的文件
- 把这个文件拖动到exe可执行文件上
- 处理完成后在此前文件夹生成一个out.pdf文件
package main
import (
// 加载字体文件内容时使用
// 使用embed可以把字体文件内容直接打包到可执行文件里 十分方便
// 缺点是可执行文件体积会变的很大
// 如果没有用过 可以去搜索学习一下
// 以下网页可以学习
// https://blog.csdn.net/RA681t58CJxsgCkJ31/article/details/113777516
// https://pkg.go.dev/embed
_ "embed"
// 所使用到的pdf库 gof pdf
// 关于这个库的更多使用方式 可以到github上查看
"github.com/jung-kurt/gofpdf"
// 对文件名称列表进行排序时使用
// 排序是直接对字符串进行的
"golang.org/x/exp/slices"
"os"
)
// 从文件加载字体文件内容 这里使用的是仿宋字体
// 这里在编译期就把文件内容放到了simfangFont变量里了
// 不需要再使用文件库进行读取了
// 也可以把 []byte 换成 string 前提是文件是个文本文件
// 为了方便使用 可以把一些工具类的放在单独的文件里
// 一来不污染逻辑代码
// 二来可以由ide提示更好的格式编辑功能
// 如 把sql语句放在单独的文件里 像 queryUsers.sql updateUser.sql
// 或 把lua脚本放在单文件里 像 redisLock.lua 等
// ide可以很好的识别这些文件及这些文件的格式并提供从修改到展示及运行的支持
//go:embed simfang.ttf
var simfangFont []byte
func main() {
// 设置页置 210mm×297mm
// P 纵向
// mm 单位设置为毫米
// A4 页面大小
//纵向 毫米 A4 210mm×297mm
pdf := gofpdf.New("P", "mm", "A4", "")
// 页脚与边界
pdf.SetFooterFunc(func() {
// 在页脚右下方显示页码
pdf.Text(200, 290, fmt.Sprintf("-%v-", pdf.PageNo()))
})
// 边框设置为上7mm,左右各5mm
// pdf底边距未找到设置方法
pdf.SetMargins(5, 7, 5)
// 添加一个新页面
// 必须这样写不写内容不出来
pdf.AddPage()
// ==============设置字体===============================================================
// 加载字体文件内容 + 设置字体
// 第一个参数设置为FangSong 此为字体家族名
// 这里可以添加不止一个字体
// 在使用时可以换着样用
pdf.AddUTF8FontFromBytes("FangSong", "normal", simfangFont) // 添加utf8字体到pdf
pdf.SetFont("FangSong", "normal", 10) // 使用仿宋字体 大小设置为10号
// =========写入内容=================================
// 从命令行参数获取要处理的文体路径列表
// 只获取第一个有用的路径参数即可
imgOrTxtFiles := os.Args[1:]
slices.SortStableFunc(imgOrTxtFiles, func(a, b string) bool {
// 使用字典排序进行名称的排序
return a < b
})
// 循环处理每一个文件
for i := range imgOrTxtFiles {
// 读取到文件的内容并处理错误情况
content, err := os.ReadFile(imgOrTxtFiles[i])
if err != nil {
panic(err)
}
// 先打印文件名称路径 高为4
pdf.MultiCell(0, 4, fmt.Sprintf("\n---%v---\n\n", imgOrTxtFiles[i]), "", "", false)
// 再打印路径 字高为4
pdf.MultiCell(0, 4, string(content), "", "", false)
}
// ==============收尾===保存===========================================================
// 换个行
pdf.Ln(-1)
// 打印结束字样
pdf.Cell(0, 5, "(结束)")
// 输出文件名叫out.pdf
err := pdf.OutputFileAndClose("out.pdf")
if err != nil {
// 处理错误情况
println(err.Error())
}
}
合并图片文件到单个pdf
- 按字典顺序命名要合并转换的文件
- 把这个文件拖动到exe可执行文件上
- 处理完成后在此前文件夹生成一个out.pdf文件
package main
import (
// 使用到的pdf库 pdfcpu
"github.com/pdfcpu/pdfcpu/pkg/api"
"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
"golang.org/x/exp/slices"
// 用于读取命令行参数
"os"
)
func main() {
// 从命令号读取所有要处理的图片文件
imgFiles := os.Args[1:]
slices.SortStableFunc(imgFiles, func(a, b string) bool {
// 对文件按名称进行字典顺序排序
// 对字符串直接对比
return a < b
})
// 设置pdf格式
// 这里没有设置为A4格式
// 由打印机打印时要注意选择适应页面选项
// 这样才会把内容缩放到合适的大小
imp, _ := api.Import("pos:full", types.POINTS)
// 写入图片文件到pdf文件 文件名为out.pdf
err := api.ImportImagesFile(imgFiles, "out.pdf", imp, nil)
if err != nil {
println(err.Error())
os.Exit(1)
return
}
println("done")
}
对pdf文件进行分割
- 把要切分的pdf文件拖动到exe可执行文件上
- 处理完成后在此前文件夹生成一系列分割后的文件
package main
import (
"fmt"
// 使用到的库 pdfcpu
"github.com/pdfcpu/pdfcpu/pkg/api"
"os"
)
func main() {
// 打印要处理的文件路径到控制台
fmt.Println(os.Args[1])
// 调用库方法 进行文件切割操作
// 成功后
// 在工作目录生成一系列此文件名为前缀页面范围为后缀的pdf文件
err := api.SplitFile(os.Args[1], ".", 25, nil)
if err != nil {
println(err.Error())
os.Exit(1)
return
}
println("done")
}
写在最后
通过写这些小工具 极大的方便了我的工作
也希望能够帮助到需要的人