-
-
Save Lioncat2002/f40306aba45ccafe39dcceca294f50dc to your computer and use it in GitHub Desktop.
pdf_utils
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package utils | |
import ( | |
"bytes" | |
"errors" | |
"io" | |
"log" | |
"time" | |
"github.com/LegalForceLawRAPC/notarysign/common/schemas" | |
"github.com/LegalForceLawRAPC/notarysign/config" | |
"github.com/LegalForceLawRAPC/notarysign/pkg/models" | |
"github.com/phpdave11/gofpdi" | |
"github.com/signintech/gopdf" | |
) | |
var pdf *gopdf.GoPdf | |
func InitGoPdf() *gopdf.GoPdf { | |
pdf := &gopdf.GoPdf{} | |
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) | |
fontData, err := config.Content.ReadFile("fonts/OpenSans-Regular.ttf") | |
if err != nil { | |
log.Panicln(err) | |
} | |
if err := pdf.AddTTFFontData("open-sans", fontData); err != nil { | |
log.Panicln(err) | |
} | |
fontData, err = config.Content.ReadFile("fonts/AmericanSignature.ttf") | |
if err != nil { | |
log.Panicln(err) | |
} | |
if err := pdf.AddTTFFontData("american-signature", fontData); err != nil { | |
log.Panicln(err) | |
} | |
fontData, err = config.Content.ReadFile("fonts/Angelina.ttf") | |
if err != nil { | |
log.Panicln(err) | |
} | |
if err := pdf.AddTTFFontData("angelina", fontData); err != nil { | |
log.Panicln(err) | |
} | |
fontData, err = config.Content.ReadFile("fonts/Autograf.ttf") | |
if err != nil { | |
log.Panicln(err) | |
} | |
if err := pdf.AddTTFFontData("autograf", fontData); err != nil { | |
log.Panicln(err) | |
} | |
fontData, err = config.Content.ReadFile("fonts/Autography.ttf") | |
if err != nil { | |
log.Panicln(err) | |
} | |
if err := pdf.AddTTFFontData("autography", fontData); err != nil { | |
log.Panicln(err) | |
} | |
fontData, err = config.Content.ReadFile("fonts/Mitchel.ttf") | |
if err != nil { | |
log.Panicln(err) | |
} | |
if err := pdf.AddTTFFontData("mitchel", fontData); err != nil { | |
log.Panicln(err) | |
} | |
fontData, err = config.Content.ReadFile("fonts/SevenDaySignature.ttf") | |
if err != nil { | |
log.Panicln(err) | |
} | |
if err := pdf.AddTTFFontData("sevenday-signature", fontData); err != nil { | |
log.Panicln(err) | |
} | |
return pdf | |
} | |
func GetTotalPdfPages(pdfBuf []byte) int { | |
pdf = InitGoPdf() | |
importer := gofpdi.NewImporter() | |
pdfReader := bytes.NewReader(pdfBuf) | |
r := io.ReadSeeker(pdfReader) | |
importer.SetSourceStream(&r) | |
totalPagesOfPdf := importer.GetNumPages() | |
return totalPagesOfPdf | |
} | |
func AddPageToPDF(pdfBuf []byte, pageNumber int) ([]byte, error) { | |
pdf = InitGoPdf() | |
importer := gofpdi.NewImporter() | |
pdfReader := bytes.NewReader(pdfBuf) | |
r := io.ReadSeeker(pdfReader) | |
importer.SetSourceStream(&r) | |
totalPagesOfPdf := importer.GetNumPages() | |
for i := 0; i < totalPagesOfPdf; i++ { | |
importedPage := pdf.ImportPageStream(&r, i+1, "/MediaBox") | |
data := importer.GetPageSizes() | |
pageWidth := data[i+1]["/MediaBox"]["w"] | |
pageHeight := data[i+1]["/MediaBox"]["h"] | |
pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
pdf.UseImportedTemplate(importedPage, 0, 0, pageWidth, pageHeight) | |
if pageNumber == i+1 { | |
pdf.AddPage() | |
//pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
} | |
} | |
var newPDFBuf bytes.Buffer | |
_, err := pdf.WriteTo(&newPDFBuf) | |
if err != nil { | |
return nil, err | |
} | |
return newPDFBuf.Bytes(), nil | |
} | |
func DuplicatePageFromPDF(pdfBuf []byte, pageNumber int) ([]byte, error) { | |
pdf = InitGoPdf() | |
importer := gofpdi.NewImporter() | |
pdfReader := bytes.NewReader(pdfBuf) | |
r := io.ReadSeeker(pdfReader) | |
importer.SetSourceStream(&r) | |
totalPagesOfPdf := importer.GetNumPages() | |
for i := 0; i < totalPagesOfPdf; i++ { | |
importedPage := pdf.ImportPageStream(&r, i+1, "/MediaBox") | |
data := importer.GetPageSizes() | |
pageWidth := data[i+1]["/MediaBox"]["w"] | |
pageHeight := data[i+1]["/MediaBox"]["h"] | |
pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
pdf.UseImportedTemplate(importedPage, 0, 0, pageWidth, pageHeight) | |
if pageNumber == i+1 { | |
pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
pdf.UseImportedTemplate(importedPage, 0, 0, pageWidth, pageHeight) | |
} | |
} | |
var newPDFBuf bytes.Buffer | |
_, err := pdf.WriteTo(&newPDFBuf) | |
if err != nil { | |
return nil, err | |
} | |
return newPDFBuf.Bytes(), nil | |
} | |
func DeletePageFromPDF(pdfBuf []byte, pageNumber int) ([]byte, error) { | |
pdf = InitGoPdf() | |
importer := gofpdi.NewImporter() | |
pdfReader := bytes.NewReader(pdfBuf) | |
r := io.ReadSeeker(pdfReader) | |
if r == nil { | |
return nil, errors.New("failed to read pdf") | |
} | |
importer.SetSourceStream(&r) | |
totalPagesOfPdf := importer.GetNumPages() | |
for i := 0; i < totalPagesOfPdf; i++ { | |
if pageNumber != i+1 { | |
importedPage := pdf.ImportPageStream(&r, i+1, "/MediaBox") | |
data := importer.GetPageSizes() | |
pageWidth := data[i+1]["/MediaBox"]["w"] | |
pageHeight := data[i+1]["/MediaBox"]["h"] | |
pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
pdf.UseImportedTemplate(importedPage, 0, 0, pageWidth, pageHeight) | |
} | |
} | |
var newPDFBuf bytes.Buffer | |
_, err := pdf.WriteTo(&newPDFBuf) | |
if err != nil { | |
return nil, err | |
} | |
return newPDFBuf.Bytes(), nil | |
} | |
func MergePDFs(pdfBufs [][]byte) ([]byte, error) { | |
// Merge PDFs in memory | |
pdf = InitGoPdf() | |
importer := gofpdi.NewImporter() | |
for _, pdfBuf := range pdfBufs { | |
if pdfBuf == nil { | |
return nil, errors.New("failed to merge pdf") | |
} | |
pdfReader := bytes.NewReader(pdfBuf) | |
r := io.ReadSeeker(pdfReader) | |
importer.SetSourceStream(&r) | |
totalPagesOfPdf := importer.GetNumPages() | |
for i := 0; i < totalPagesOfPdf; i++ { | |
importedPage := pdf.ImportPageStream(&r, i+1, "/MediaBox") | |
data := importer.GetPageSizes() | |
pageWidth := data[i+1]["/MediaBox"]["w"] | |
pageHeight := data[i+1]["/MediaBox"]["h"] | |
pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
pdf.UseImportedTemplate(importedPage, 0, 0, pageWidth, pageHeight) | |
} | |
} | |
var mergedPDFBuf bytes.Buffer | |
_, err := pdf.WriteTo(&mergedPDFBuf) | |
if err != nil { | |
return nil, err | |
} | |
return mergedPDFBuf.Bytes(), nil | |
} | |
func GenerateSignedPdf(pdfBuf []byte, documentFields []schemas.DocumentFieldFetchData) ([]byte, error) { | |
pdf = InitGoPdf() | |
importer := gofpdi.NewImporter() | |
pdfReader := bytes.NewReader(pdfBuf) | |
r := io.ReadSeeker(pdfReader) | |
importer.SetSourceStream(&r) | |
totalPagesOfPdf := importer.GetNumPages() | |
for i := 0; i < totalPagesOfPdf; i++ { | |
importedPage := pdf.ImportPageStream(&r, i+1, "/MediaBox") | |
data := importer.GetPageSizes() | |
pageWidth := data[i+1]["/MediaBox"]["w"] | |
pageHeight := data[i+1]["/MediaBox"]["h"] | |
pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
pdf.UseImportedTemplate(importedPage, 0, 0, pageWidth, pageHeight) | |
for _, field := range documentFields { | |
if field.PageNumber == i+1 { | |
if field.Signature != "" { | |
img, err := GetObjectContentInS3(field.Signature) | |
if err != nil { | |
return nil, err | |
} | |
imgHolder, err := gopdf.ImageHolderByBytes(img) | |
if err != nil { | |
return nil, err | |
} | |
pdf.ImageByHolder(imgHolder, field.X, field.Y, &gopdf.Rect{W: field.Width, H: field.Height}) | |
} else if field.StringSignature != "" { | |
pdf.SetXY(field.X, field.Y) | |
pdf.SetFont("open-sans", "", field.FontSize) | |
err := pdf.Text(field.StringSignature) | |
if err != nil { | |
return nil, err | |
} | |
} | |
} | |
} | |
} | |
var signedPDFBuf bytes.Buffer | |
_, err := pdf.WriteTo(&signedPDFBuf) | |
if err != nil { | |
return nil, err | |
} | |
return signedPDFBuf.Bytes(), nil | |
} | |
func GenerateSignerCertificate(documentFields []schemas.DocumentFieldFetchData) ([]byte, error) { | |
pdf = InitGoPdf() | |
y := 100.0 | |
pdf.AddPage() | |
if err := pdf.SetFont("open-sans", "", 12); err != nil { | |
return nil, err | |
} | |
if err := drawCell(pdf, "Name\tTimestamp\tSignature", 20, y); err != nil { | |
return nil, err | |
} | |
for i, field := range documentFields { | |
if err := pdf.SetFont("open-sans", "", 12); err != nil { | |
return nil, err | |
} | |
if err := drawCell(pdf, field.AssigneeName, 20, y); err != nil { | |
return nil, err | |
} | |
if err := pdf.SetFont("open-sans", "", 8); err != nil { | |
return nil, err | |
} | |
time := time.Unix(int64(field.UpdatedAt), 0) | |
if err := drawCell(pdf, time.UTC().String(), 120, y); err != nil { | |
return nil, err | |
} | |
if field.StringSignature != "" { | |
if err := pdf.SetFont("open-sans", "", 12); err != nil { | |
return nil, err | |
} | |
if err := drawCell(pdf, field.StringSignature, 360, y); err != nil { | |
return nil, err | |
} | |
} else if field.Signature != "" { | |
if err := drawImage(pdf, field.Signature, 360, y, field.Width, field.Height); err != nil { | |
return nil, err | |
} | |
} | |
y += 30 | |
if (i+1)%3 == 0 && i != len(documentFields)-1 { | |
pdf.AddPage() | |
y = 100.0 // Reset Y position for the next page | |
} | |
} | |
var signerCertificateBuf bytes.Buffer | |
_, err := pdf.WriteTo(&signerCertificateBuf) | |
if err != nil { | |
return nil, err | |
} | |
return signerCertificateBuf.Bytes(), nil | |
} | |
func GenerateAttachmentPdf(pdfBuf []byte, attachments []models.Attachment) ([]byte, error) { | |
pdf = InitGoPdf() | |
importer := gofpdi.NewImporter() | |
pdfReader := bytes.NewReader(pdfBuf) | |
r := io.ReadSeeker(pdfReader) | |
importer.SetSourceStream(&r) | |
totalPagesOfPdf := importer.GetNumPages() | |
for i := 0; i < totalPagesOfPdf; i++ { | |
importedPage := pdf.ImportPageStream(&r, i+1, "/MediaBox") | |
data := importer.GetPageSizes() | |
pageWidth := data[i+1]["/MediaBox"]["w"] | |
pageHeight := data[i+1]["/MediaBox"]["h"] | |
pdf.AddPageWithOption(gopdf.PageOption{PageSize: &gopdf.Rect{W: pageWidth, H: pageHeight}}) | |
pdf.UseImportedTemplate(importedPage, 0, 0, pageWidth, pageHeight) | |
for _, attachment := range attachments { | |
if attachment.PageNumber == i+1 { | |
img, err := GetObjectContentInS3(attachment.AttachmentS3Key) | |
if err != nil { | |
return nil, err | |
} | |
imgHolder, err := gopdf.ImageHolderByBytes(img) | |
if err != nil { | |
return nil, err | |
} | |
pdf.ImageByHolder(imgHolder, attachment.X, attachment.Y, &gopdf.Rect{W: attachment.Width, H: attachment.Height}) | |
} | |
} | |
} | |
var attachmentPDFBuf bytes.Buffer | |
_, err := pdf.WriteTo(&attachmentPDFBuf) | |
if err != nil { | |
return nil, err | |
} | |
return attachmentPDFBuf.Bytes(), nil | |
} | |
func drawCell(pdf *gopdf.GoPdf, text string, x, y float64) error { | |
pdf.SetXY(x, y) | |
err := pdf.Cell(nil, text) | |
if err != nil { | |
return err | |
} | |
return nil | |
} | |
func drawImage(pdf *gopdf.GoPdf, key string, x, y, w, h float64) error { | |
img, err := GetObjectContentInS3(key) | |
if err != nil { | |
return err | |
} | |
imgHolder, err := gopdf.ImageHolderByBytes(img) | |
if err != nil { | |
return err | |
} | |
pdf.ImageByHolder(imgHolder, x, y, &gopdf.Rect{W: w, H: h}) | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment