signintech / gopdf

A simple library for generating PDF written in Go lang
MIT License
2.53k stars 273 forks source link

Import existing PDF into GoPDF Document #109

Open phpdave11 opened 5 years ago

phpdave11 commented 5 years ago

Hi! I have created a go package called gofpdi (Go Free PDF Document Importer) that allows you to import PDFs. I have created a pull request that integrates gofpdi with gopdf, allowing you to embed a PDF into your GoPDF document.

phpdave11 commented 5 years ago

Here's an example of how it works:

package main

import (
        "github.com/phpdave11/gopdf"
        "io"
        "net/http"
        "os"
)

func main() {
        var err error

        // Download a Font
        fontUrl := "https://github.com/google/fonts/raw/master/ofl/daysone/DaysOne-Regular.ttf"
        if err = DownloadFile("example-font.ttf", fontUrl); err != nil {
                panic(err)
        }

        // Download a PDF
        fileUrl := "https://tcpdf.org/files/examples/example_012.pdf"
        if err = DownloadFile("example-pdf.pdf", fileUrl); err != nil {
                panic(err)
        }

        pdf := gopdf.GoPdf{}
        pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4

        pdf.AddPage()

        err = pdf.AddTTFFont("daysone", "example-font.ttf")
        if err != nil {
                panic(err)
        }

        err = pdf.SetFont("daysone", "", 20)
        if err != nil {
                panic(err)
        }

        // Color the page
        pdf.SetLineWidth(0.1)
        pdf.SetFillColor(124, 252, 0) //setup fill color
        pdf.RectFromUpperLeftWithStyle(50, 100, 400, 600, "FD")
        pdf.SetFillColor(0, 0, 0)

        pdf.SetX(50)
        pdf.SetY(50)
        pdf.Cell(nil, "Import existing PDF into GoPDF Document")

        // Import page 1
        tpl1 := pdf.ImportPage("example-pdf.pdf", 1, "/MediaBox")

        // Draw pdf onto page
        pdf.UseImportedTemplate(tpl1, 50, 100, 400, 0)

        pdf.WritePdf("example.pdf")

}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {
        // Get the data
        resp, err := http.Get(url)
        if err != nil {
                return err
        }
        defer resp.Body.Close()

        // Create the file
        out, err := os.Create(filepath)
        if err != nil {
                return err
        }
        defer out.Close()

        // Write the body to file
        _, err = io.Copy(out, resp.Body)
        return err
}

Generated PDF:

example.pdf

Screenshot of PDF:

example

jung-kurt commented 5 years ago

Awesome! This feature has been requested more than once. I look forward to studying it.

In order to integrate it with gofpdf which depends only on the Go standard library, the package that imports gofpdi (with the ImportPage() method) will go into the contrib directory (version 1) and the gofpdfcontrib repository (version 2).

tao-s commented 5 years ago

@phpdave11 @oneplus1000 I wrote how-to-use this finction in Japanese. https://qiita.com/tao_s/items/be145dc85169689a2a4f

phpdave11 commented 5 years ago

English translation of https://qiita.com/tao_s/items/be145dc85169689a2a4f

Embed in PDF of template using gopdf with Go 1.12

There is a case "I want to receive the form value of the Web and generate PDF". Go In response to v1. 12, I tried using a Thai-made library that works fine and does not garble or shift even Japanese fonts.

https://github.com/signintech/gopdf/releases/tag/v.0.9.2

It is safe because it is the same multi-byte culture area

Go PDF Library, gopdf Is a PDF generation library for Go developed by Signin Technology of Thailand. I do not know whether it is because it is the same multi-byte language category or because there are many Chinese-language jobs, but since it also supports kerning of Japanese fonts, it is possible to generate Japanese PDFs beautifully without shifting. You

gopdf is a simple library for generating pdf document written in go lang.

Features -Unicode subfont embedding. (Chinese, Japanese, Korean, etc.) -Draw line, oval, rect, curve -Draw image (jpg, png) -Password protection -Font kerning

Other PDF can be used as a template

gofpdi Because it is embedded, you can use the PDF file output by Word, Excel etc. as a template file. It looks like a merge. The requirement was to automate the PDF creation work that was previously generated by MS Office, but not to change the appearance of PDF, so it was a batch. However, once PDF was changed in the preview of the Mac, there was a reading error, so there may be some restrictions on the version of the PDF to be based.

How to use

import

First, import gopdf. If you are using v. 0.9. 2 or later, gofpdi v1. 0.5 or more will be imported and templates will be usable.

 import  ( 
     "github.com/signintech/gopdf" 
 )

Initialization

pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
pdf.AddPage()

Load template

After drawing the template PDF and adding text, it will be added to the layer above the template PDF. Conversely, if you draw a template PDF after adding elements, it will be added to the layer under the template PDF.

// import template file 
tpl := pdf.ImportPage("./template.pdf", 1, "/MediaBox") // 1 is the page 
// Draw pdf onto page 
pdf.UseImportedTemplate(tpl, 0, 0, 595.28, 841.89) // Template structure, x coordinate, y coordinate, width, height

As described above, you can select the coordinates and size to draw at the time of drawing, so it is possible to embed and shrink.

Load font

Japanese font is required to display Japanese. Place the font file in an appropriate directory on the server and read it as follows. This time is trust and results IPA font I used It is possible to use OpenType other than TrueType, but I have not tried this time. In addition, CJK font of Google font is disliked because the character shape of kanji changes and it becomes somewhat shady.

err := pdf.AddTTFFont("ipagp", "./font/ipagp.ttf")
if err != nil {
    panic(err)
}

Add string

pdf.SetFont("ipagp", "", 12)  // font, character size specification 
pdf.SetX(10) // x coordinate specification 
pdf.SetY(10) // y coordinate specification 
pdf.Cell(nil, "Thank you! Signintech & phpdave11"  ) // Rect, String 

// When specifying justification 
op := gopdf.CellOption{Align: gopdf.Center} // Center alignment 
rect := gopdf.Rect{W: 400, H: 20}
pdf.CellWithOption(&rect, "Thank you! signintech & phpdave11", op)

Add image from byte data

In the sample, the image file was read and added to the PDF, but this time, I wanted to generate and add a QR code, so I embedded byte data. We will write about QR code generation separately.

ih, err := gopdf.ImageHolderByBytes(generateQRcode()) // generateQRcode () returns [] byte 
pdf.ImageByHolder(ih, 517, 325, nil) // Embed the image using the image holder 

output

pdf.Write(w) // in this case w is http.ResponseWriter

The above code will display the PDF file in the browser. If you output the HTTP header correctly, it will feel like the download will start. If you want to save it on the server as a file

pdf.WritePdf("thankyou.pdf")

will do.

This time, I tried PDF editing with Go for the first time, but it was easier than I imagined and it was fun. However, the version of gofpdi specified in gopdf did not fit and I could not read the PDF properly, or I stepped on a little landmines, but it felt like I was expecting. https://github.com/signintech/gopdf/pull/113

It works with Google Cloud AppEngine!

This time, I used Google Cloud AppEngine for development, but it worked comfortably and development was easy. When using with AppEngine, in app.yaml

phpdave11 commented 5 years ago

@tao-s thanks for the write-up, and thanks for submitting the pull request to update the gofpdi version to v1.0.5!

tao-s commented 5 years ago

@phpdave11 Wow! Thank you very very much! Did you use Google translator? My Engkish is not good, I worry the translation as well. Because that Japanese post is not formal Japanese style.

phpdave11 commented 5 years ago

@tao-s google translator didn't work, so I used bablic translator. I was able to understand it.

vantaboard commented 3 months ago

@oneplus1000 can you close this issue if it has been resolved?