La generazione di PDF dinamici in Go può essere semplice quando si utilizzano librerie come gofpdf
. Tuttavia, per molte applicazioni è necessario un layout più complesso, comprendente un header, un logo e testo formattato. In questo articolo vedremo come creare un endpoint REST in Go che produce PDF in modo dinamico con Gin, includendo elementi grafici e formattazione avanzata.
Prerequisiti
Assicurati di avere Go installato e aggiungi le dipendenze necessarie:
go get github.com/gin-gonic/gin
go get github.com/jung-kurt/gofpdf
Struttura dell'applicazione
L'applicazione prevede:
- Un endpoint
POST
che riceve i dati per il PDF. - Una funzione per generare il PDF con layout avanzato.
- Header personalizzato con logo e data.
- Testo formattato con paragrafi.
Codice di esempio
package main
import (
"bytes"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/jung-kurt/gofpdf"
)
type PDFRequest struct {
Title string `json:"title"`
Content []string `json:"content"`
}
func generatePDF(title string, content []string) ([]byte, error) {
pdf := gofpdf.New("P", "mm", "A4", "")
pdf.SetMargins(20, 20, 20)
pdf.AddPage()
addHeader(pdf, title)
addBody(pdf, content)
var buf bytes.Buffer
if err := pdf.Output(&buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func addHeader(pdf *gofpdf.Fpdf, title string) {
pdf.ImageOptions("logo.png", 10, 10, 30, 0, false, gofpdf.ImageOptions{}, 0, "")
pdf.SetY(15)
pdf.SetX(45)
pdf.SetFont("Arial", "B", 20)
pdf.Cell(100, 10, title)
pdf.SetFont("Arial", "", 12)
pdf.SetXY(160, 15)
pdf.CellFormat(40, 10, time.Now().Format("02/01/2006"), "", 0, "R", false, 0, "")
pdf.Ln(20)
pdf.Line(10, pdf.GetY(), 200, pdf.GetY())
pdf.Ln(10)
}
func addBody(pdf *gofpdf.Fpdf, paragraphs []string) {
pdf.SetFont("Arial", "", 12)
for _, p := range paragraphs {
pdf.MultiCell(0, 8, p, "", "", false)
pdf.Ln(3)
}
}
func pdfHandler(c *gin.Context) {
var req PDFRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
pdfBytes, err := generatePDF(req.Title, req.Content)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate PDF"})
return
}
c.Header("Content-Type", "application/pdf")
c.Header("Content-Disposition", `inline; filename="custom-report.pdf"`)
c.Data(http.StatusOK, "application/pdf", pdfBytes)
}
func main() {
router := gin.Default()
router.POST("/generate-pdf", pdfHandler)
router.Run(":8080")
}
Test dell'endpoint
Puoi testare il servizio con un comando curl, salvando direttamente il PDF generato:
curl -X POST http://localhost:8080/generate-pdf \
-H "Content-Type: application/json" \
-d '{
"title": "Report Mensile",
"content": [
"Benvenuto al nostro report mensile.",
"Le vendite sono aumentate del 15% rispetto al mese scorso.",
"Grazie per l’attenzione."
]
}' --output report.pdf
Considerazioni finali
Con gofpdf
e Gin è possibile generare PDF direttamente in memoria, senza scriverli su disco, offrendo così una risposta rapida e personalizzata al client. L'esempio mostrato può essere esteso con tabelle, piè di pagina, font personalizzati e contenuti multilingua. Per layout HTML complessi si possono valutare soluzioni alternative come unipdf
o chromedp
per il rendering HTML-to-PDF.