golang基于JSON请求生成PDF的HTTP服务插件库pdfgen的使用
Golang基于JSON请求生成PDF的HTTP服务插件库pdfgen的使用
安装和运行
推荐使用Docker容器运行,通过挂载模板目录(这里使用提供的示例template
目录):
docker run --rm -it -p 8888:8888 \
--mount src=my_templates/,target=/etc/pdfgen/templates,type=bind \
hyperboloide/pdfgen
如果不使用Docker,需要先安装wkhtmltopdf,然后运行:
go install github.com/hyperboloide/pdfgen
PDFGEN_TEMPLATES=./templates pdfgen
安装后可以通过以下命令测试:
curl -H "Content-Type: application/json" -X POST -d @my_json_file.json \
http://localhost:8888/invoice > result.pdf
注意:渲染结果可能因操作系统(特别是OSX)和安装的字体而有所不同,因此建议在Docker环境中进行测试和开发,以确保生产环境中的结果一致。
模板
PDF是从HTML模板生成的。这些模板与Django模板非常相似。
例如以下模板:
<h1>Hello, {{ user }}</h1>
可以通过application/json
POST请求生成:
{"user": "fred"}
响应类型为application/pdf
,包含生成的PDF文件。
每个PDF模板都应该有自己的目录,位于PDFGEN_TEMPLATES
环境变量定义的根目录下。
URL端点将从这些目录名称生成。例如,invoice
目录中的模板将可以通过类似http://host:port/invoice
的URL访问。
模板目录必须包含一个index.html
文件,可选地包含一个footer.html
文件。其他资源如图像和CSS也应该放在该目录中。
注意:每个PDF都是独立生成的,因此模板应该使用绝对路径。例如:
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css" media='screen,print'>
最后,不要忘记将PDFGEN_TEMPLATES
环境变量设置为模板父目录的路径。或者,您可以将模板复制到以下任一位置:
/etc/pdfgen/templates
或~/.templates
。
添加字体
您可以创建一个包含字体并重建缓存的新容器。以下是Dockerfile示例:
FROM hyperboloide/pdfgen
COPY my_fonts /usr/local/share/fonts/
RUN fc-cache -f -v
完整示例
1. 创建模板目录结构
my_templates/
└── invoice
├── index.html
└── style.css
2. 示例index.html
<!DOCTYPE html>
<html>
<head>
<title>Invoice</title>
<link rel="stylesheet" href="/invoice/style.css">
</head>
<body>
<h1>Invoice #{{ .number }}</h1>
<p>Date: {{ .date }}</p>
<p>Customer: {{ .customer }}</p>
<table>
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{{ range .items }}
<tr>
<td>{{ .name }}</td>
<td>{{ .quantity }}</td>
<td>${{ .price }}</td>
</tr>
{{ end }}
</tbody>
</table>
<p class="total">Total: ${{ .total }}</p>
</body>
</html>
3. 示例JSON请求
{
"number": "INV-2023-001",
"date": "2023-05-15",
"customer": "John Doe",
"items": [
{"name": "Product A", "quantity": 2, "price": 50.00},
{"name": "Product B", "quantity": 1, "price": 75.50},
{"name": "Service C", "quantity": 3, "price": 20.00}
],
"total": 205.50
}
4. 生成PDF的命令
curl -H "Content-Type: application/json" -X POST -d @invoice_data.json \
http://localhost:8888/invoice > invoice.pdf
5. Go代码集成示例
package main
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"os"
)
func main() {
// 准备JSON数据
invoiceData := map[string]interface{}{
"number": "INV-2023-001",
"date": "2023-05-15",
"customer": "John Doe",
"items": []map[string]interface{}{
{"name": "Product A", "quantity": 2, "price": 50.00},
{"name": "Product B", "quantity": 1, "price": 75.50},
{"name": "Service C", "quantity": 3, "price": 20.00},
},
"total": 205.50,
}
jsonData, err := json.Marshal(invoiceData)
if err != nil {
panic(err)
}
// 发送请求到pdfgen服务
resp, err := http.Post("http://localhost:8888/invoice", "application/json", bytes.NewBuffer(jsonData))
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 读取PDF响应
pdfBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
// 保存PDF文件
err = ioutil.WriteFile("invoice.pdf", pdfBytes, 0644)
if err != nil {
panic(err)
}
}
更多关于golang基于JSON请求生成PDF的HTTP服务插件库pdfgen的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于JSON请求生成PDF的HTTP服务插件库pdfgen的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用pdfgen库基于JSON请求生成PDF的HTTP服务
pdfgen是一个Go语言库,用于基于JSON请求生成PDF文档。下面我将详细介绍如何使用这个库创建一个HTTP服务来生成PDF。
安装pdfgen
首先,确保你已经安装了Go环境(1.13+),然后使用以下命令安装pdfgen:
go get github.com/pdfgen-dev/pdfgen
基本HTTP服务示例
下面是一个完整的HTTP服务示例,它接收JSON请求并返回生成的PDF:
package main
import (
"log"
"net/http"
"os"
"github.com/pdfgen-dev/pdfgen/pkg/pdf"
)
func main() {
// 创建HTTP处理器
http.HandleFunc("/generate-pdf", generatePDFHandler)
// 启动HTTP服务器
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("Server starting on port %s...", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
func generatePDFHandler(w http.ResponseWriter, r *http.Request) {
// 只接受POST请求
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 解析JSON请求体
var request pdf.GenerateRequest
if err := pdf.ParseGenerateRequest(r, &request); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 生成PDF
pdfBytes, err := pdf.Generate(&request)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 设置响应头
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", "attachment; filename=generated.pdf")
// 写入PDF内容
if _, err := w.Write(pdfBytes); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
JSON请求格式
pdfgen接受的JSON请求通常包含以下字段:
{
"html": "<html><body><h1>Hello World</h1></body></html>",
"options": {
"margin": {
"top": "10mm",
"right": "10mm",
"bottom": "10mm",
"left": "10mm"
},
"format": "A4",
"orientation": "portrait"
}
}
高级配置
1. 自定义PDF选项
options := pdf.Options{
Margin: pdf.Margin{
Top: "20mm",
Right: "20mm",
Bottom: "20mm",
Left: "20mm",
},
Format: "Letter",
Orientation: "landscape",
Header: &pdf.HeaderFooter{
HTML: "<div style='text-align: center;'>Page Header</div>",
},
Footer: &pdf.HeaderFooter{
HTML: "<div style='text-align: center;'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></div>",
},
}
2. 使用模板
pdfgen支持使用Go模板来动态生成HTML:
request := pdf.GenerateRequest{
Template: pdf.Template{
Name: "invoice",
Data: map[string]interface{}{
"invoiceNumber": "INV-2023-001",
"date": "2023-01-01",
"items": []map[string]interface{}{
{"name": "Item 1", "price": 100},
{"name": "Item 2", "price": 200},
},
},
},
Options: options,
}
3. 添加自定义字体
options := pdf.Options{
Fonts: []pdf.Font{
{
Family: "Roboto",
Style: "normal",
Weight: "400",
Src: []pdf.FontSrc{
{URL: "https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxK.woff2"},
},
},
},
}
部署建议
- Docker部署:可以将服务打包为Docker容器方便部署
- 性能优化:对于高并发场景,考虑添加缓存或限流机制
- 安全性:添加API密钥验证或JWT认证
错误处理
pdfgen会返回详细的错误信息,建议在生产环境中记录这些错误:
pdfBytes, err := pdf.Generate(&request)
if err != nil {
log.Printf("PDF生成失败: %v", err)
http.Error(w, "PDF生成失败", http.StatusInternalServerError)
return
}
总结
pdfgen库提供了一个简单而强大的方式来基于JSON请求生成PDF。通过上面的示例,你可以快速搭建一个PDF生成服务,并根据需要进行扩展。记得根据你的具体需求调整PDF选项和错误处理逻辑。