Golang实现PDF文件打印到Windows打印机
Golang实现PDF文件打印到Windows打印机 大家好
我使用gofpdf创建了一个包含一些简单格式的简单PDF文件,并希望在Windows机器上使用标签打印机打印此PDF。使用纯文本可以正常工作,但PDF不行。有人能给我一个示例吗?那将非常有帮助。
我将gofpdf的输出作为字节切片传递给这个函数。但我遇到了打印机错误:
var buf bytes.Buffer
pdf.Output(&buf)
print2(buf.Bytes())
func print2(content []byte) {
fmt.Println(string(content))
name, err := prt.Default() // 以字符串形式返回默认打印机的名称
if err != nil {
fmt.Println(err)
}
fmt.Println(name)
p, err := prt.Open(name) // 打开指定名称的打印机并返回一个*Printer
if err != nil {
fmt.Println(err)
}
//err = p.StartDocument("test", "text") // test: 文档名称, text: 文档类型
err = p.StartDocument("test", "RAW")
if err != nil {
fmt.Println(err)
}
err = p.StartPage() // 开始新页面
if err != nil {
fmt.Println(err)
}
//n, err := p.Write([]byte("Hello, Printer!")) // 向打印机发送一些文本
n, err := p.Write(content) // 向打印机发送一些文本
if err != nil {
fmt.Println(err)
}
fmt.Println("写入打印机的字节数:", n)
err = p.EndPage() // 页面结束
if err != nil {
fmt.Println(err)
}
err = p.EndDocument() // 文档结束
if err != nil {
fmt.Println(err)
}
err = p.Close() // 关闭资源
if err != nil {
fmt.Println(err)
}
}
或者,是否可以将gofpdf生成的文件直接发送到打印机?我已经没有头绪了……
感谢您的帮助!
更多关于Golang实现PDF文件打印到Windows打印机的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你好,@Dino,
你提供的示例代码不完整,无法编译源代码供我自己测试。你是否在 GitHub 或其他地方有完整的代码?
更多关于Golang实现PDF文件打印到Windows打印机的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我不知道打印机上具体的错误信息是什么。PDF文件被正确发送,从代码中没有产生任何错误信息。如果我将PDF保存到磁盘并用PDF阅读器打开,它看起来完全正常。错误应该出现在发送给打印机的消息格式中的某个地方。你可以测试一下,如果你从磁盘上随便拿一个其他PDF文件,并通过代码发送到你的打印机。
在Windows上打印PDF文件需要使用专门的打印处理器,不能直接将PDF原始数据作为RAW数据发送。以下是几种解决方案:
方案1:使用Windows打印处理器(推荐)
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"github.com/jung-kurt/gofpdf"
"github.com/danicat/simplego/printer"
)
func createPDF() []byte {
pdf := gofpdf.New("P", "mm", "A4", "")
pdf.AddPage()
pdf.SetFont("Arial", "B", 16)
pdf.Cell(40, 10, "Hello, Printer!")
pdf.Ln(12)
pdf.SetFont("Arial", "", 12)
pdf.Cell(40, 10, "This is a test PDF document.")
var buf bytes.Buffer
pdf.Output(&buf)
return buf.Bytes()
}
func printPDFWithWindows(pdfData []byte) error {
// 创建临时文件
tmpFile, err := os.CreateTemp("", "print_*.pdf")
if err != nil {
return err
}
defer os.Remove(tmpFile.Name())
// 写入PDF数据
if _, err := tmpFile.Write(pdfData); err != nil {
return err
}
tmpFile.Close()
// 使用Windows命令打印
cmd := exec.Command("cmd", "/C", "start", "/min", "", tmpFile.Name())
return cmd.Run()
}
func main() {
pdfData := createPDF()
if runtime.GOOS == "windows" {
if err := printPDFWithWindows(pdfData); err != nil {
fmt.Printf("打印失败: %v\n", err)
} else {
fmt.Println("PDF已发送到默认打印机")
}
}
}
方案2:使用第三方库(如go-ole)
package main
import (
"bytes"
"fmt"
"os"
"path/filepath"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
"github.com/jung-kurt/gofpdf"
)
func printPDFViaCOM(pdfData []byte) error {
ole.CoInitialize(0)
defer ole.CoUninitialize()
// 创建临时PDF文件
tmpDir := os.TempDir()
pdfPath := filepath.Join(tmpDir, "print_temp.pdf")
if err := os.WriteFile(pdfPath, pdfData, 0644); err != nil {
return err
}
defer os.Remove(pdfPath)
// 使用Shell执行打印
unknown, err := oleutil.CreateObject("Shell.Application")
if err != nil {
return err
}
defer unknown.Release()
shell, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return err
}
defer shell.Release()
// 调用ShellExecute方法打印
oleutil.CallMethod(shell, "ShellExecute", pdfPath, "Print", "", "open")
return nil
}
func main() {
pdf := gofpdf.New("P", "mm", "A4", "")
pdf.AddPage()
pdf.SetFont("Arial", "B", 16)
pdf.Cell(40, 10, "Test Print")
var buf bytes.Buffer
pdf.Output(&buf)
if err := printPDFViaCOM(buf.Bytes()); err != nil {
fmt.Printf("打印错误: %v\n", err)
}
}
方案3:使用外部工具(如SumatraPDF)
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"github.com/jung-kurt/gofpdf"
)
func printWithSumatraPDF(pdfData []byte) error {
// 创建临时文件
tmpFile, err := os.CreateTemp("", "print_*.pdf")
if err != nil {
return err
}
defer os.Remove(tmpFile.Name())
// 写入PDF数据
if _, err := tmpFile.Write(pdfData); err != nil {
return err
}
tmpFile.Close()
// SumatraPDF命令行打印
// 需要先安装SumatraPDF: https://www.sumatrapdfreader.org/download-free-pdf-viewer
cmd := exec.Command("SumatraPDF.exe", "-print-to-default", tmpFile.Name())
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
func main() {
pdf := gofpdf.New("P", "mm", "A4", "")
pdf.AddPage()
pdf.SetFont("Arial", "B", 16)
pdf.Cell(40, 10, "Print Test")
var buf bytes.Buffer
pdf.Output(&buf)
if err := printWithSumatraPDF(buf.Bytes()); err != nil {
fmt.Printf("打印错误: %v\n", err)
}
}
方案4:使用RAW打印但转换为打印机语言(针对标签打印机)
如果您的标签打印机支持PCL、PostScript或ZPL等页面描述语言:
package main
import (
"bytes"
"fmt"
"github.com/jung-kurt/gofpdf"
"github.com/danicat/simplego/printer"
)
func convertPDFToPCL(pdfData []byte) ([]byte, error) {
// 这里需要PDF到PCL的转换库
// 可以使用外部工具如Ghostscript或pdftopcl
// 这是一个示例框架
return pdfData, nil
}
func printToLabelPrinter(pdfData []byte) error {
prtName, err := printer.Default()
if err != nil {
return err
}
p, err := printer.Open(prtName)
if err != nil {
return err
}
defer p.Close()
// 转换为打印机可接受的格式
printerData, err := convertPDFToPCL(pdfData)
if err != nil {
return err
}
err = p.StartDocument("label", "RAW")
if err != nil {
return err
}
_, err = p.Write(printerData)
if err != nil {
return err
}
return p.EndDocument()
}
func main() {
pdf := gofpdf.New("P", "mm", "A4", "")
pdf.AddPage()
pdf.SetFont("Arial", "B", 16)
pdf.Cell(40, 10, "Label Content")
var buf bytes.Buffer
pdf.Output(&buf)
if err := printToLabelPrinter(buf.Bytes()); err != nil {
fmt.Printf("打印错误: %v\n", err)
}
}
关键点:
- PDF是页面描述格式,不能直接作为RAW数据发送到打印机
- Windows需要打印处理器来解析PDF并转换为打印机语言
- 对于标签打印机,可能需要先将PDF转换为打印机支持的语言(如ZPL、EPL等)
- 最简单的方法是使用Windows内置的打印功能或外部工具

