Skip to content

Commit

Permalink
Merge pull request #245 from unidoc/us-392-file-attachment-examples
Browse files Browse the repository at this point in the history
[US-392] File attachment examples
  • Loading branch information
3ace authored Apr 17, 2024
2 parents 74f6a72 + 9d8ed19 commit 8a0f752
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 1,430 deletions.
8 changes: 8 additions & 0 deletions attachment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# File Attachments

Exemplify how to attach files into a PDF document and retrieves it.

## Examples

- [pdf_add_attachment.go](pdf_add_attachment.go) Attach files into a PDF document, either by manually loading the file content or passing the file name.
- [pdf_get_attachment.go](pdf_get_attachment.go) Retrieve list of file attachment and save it locally.
6 changes: 6 additions & 0 deletions attachment/dummy.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Binary file added attachment/minimal.pdf
Binary file not shown.
122 changes: 122 additions & 0 deletions attachment/pdf_add_attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Attach files into PDF document either by passing the file name or by passing the file content.
*/

package main

import (
"fmt"
"os"

"github.com/gabriel-vasile/mimetype"
"github.com/unidoc/unipdf/v3/common/license"
"github.com/unidoc/unipdf/v3/model"
)

func init() {
// Make sure to load your metered License API key prior to using the library.
// If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
if err != nil {
panic(err)
}
}

func main() {
inputPath := "minimal.pdf"
outputPath := "output.pdf"
xmlFile := "dummy.xml"

err := addAttachment(inputPath, xmlFile, outputPath)
if err != nil {
fmt.Printf("Failed to add attachment: %v", err)

os.Exit(1)
}

fmt.Printf("Success, output in %s\n", outputPath)
}

func addAttachment(inputPath string, attachment string, outputPath string) error {
// Read the input pdf file.
f, err := os.Open(inputPath)
if err != nil {
return err
}
defer f.Close()

pdfReader, err := model.NewPdfReader(f)
if err != nil {
return err
}

pdfWriter, err := pdfReader.ToWriter(nil)
if err != nil {
return err
}

for i := 0; i < 5; i++ {
// Instantiate embedded file object from existing file path.
emFile, err := model.NewEmbeddedFile(attachment)
if err != nil {
return err
}

// Overwrite attachment name.
emFile.Name = fmt.Sprintf("dummy%d.xml", i+1)
emFile.Description = fmt.Sprintf("Sample Attachment %d", i+1)
emFile.Relationship = model.RelationshipData

err = pdfWriter.AttachFile(emFile)
if err != nil {
return err
}
}

return pdfWriter.WriteToFile(outputPath)
}

func addAttachmentFromContent(inputPath string, attachment string, outputPath string) error {
// Read the input pdf file.
f, err := os.Open(inputPath)
if err != nil {
return err
}
defer f.Close()

pdfReader, err := model.NewPdfReader(f)
if err != nil {
return err
}

pdfWriter, err := pdfReader.ToWriter(nil)
if err != nil {
return err
}

// Get attachment file content.
content, err := os.ReadFile(attachment)
if err != nil {
return err
}

for i := 0; i < 2; i++ {
// Instantiate embedded file object from existing file content.
eFile, err := model.NewEmbeddedFileFromContent(content)
if err != nil {
return err
}

eFile.Name = fmt.Sprintf("dummy%d.xml", i+1)
eFile.Description = fmt.Sprintf("Sample Attachment %d", i+1)
eFile.FileType = mimetype.Detect(content).String()
eFile.Relationship = model.RelationshipData

err = pdfWriter.AttachFile(eFile)
if err != nil {
return err
}
}

return pdfWriter.WriteToFile(outputPath)
}
73 changes: 73 additions & 0 deletions attachment/pdf_get_attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Retrieve list of attachment file and save it locally.
*/

package main

import (
"fmt"
"os"
"path/filepath"

"github.com/unidoc/unipdf/v3/common/license"
"github.com/unidoc/unipdf/v3/model"
)

func init() {
// Make sure to load your metered License API key prior to using the library.
// If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
if err != nil {
panic(err)
}
}

func main() {
inputPath := "output.pdf"

err := listAttachments(inputPath)
if err != nil {
fmt.Printf("%v\n", err)
os.Exit(1)
}

fmt.Println("Done")
}

func listAttachments(inputPath string) error {
// Read the input pdf file.
f, err := os.Open(inputPath)
if err != nil {
return err
}
defer f.Close()

pdfReader, err := model.NewPdfReader(f)
if err != nil {
return err
}

files, err := pdfReader.GetAttachedFiles()
if err != nil {
return err
}

_, err = os.Stat("output")
if os.IsNotExist(err) {
err = os.Mkdir("output", 0777)
if err != nil {
return err
}
}

for _, v := range files {
err := os.WriteFile(filepath.Join("output", fmt.Sprintf("%s.xml", v.Name)), v.Content, 0655)
if err != nil {
return err
}

fmt.Printf("Name: %s; Hash: %s\n", v.Name, v.Hash)
}

return nil
}
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ require (
github.com/aws/aws-sdk-go v1.44.130
github.com/bmatcuk/doublestar v1.3.4
github.com/boombuler/barcode v1.0.1
github.com/gabriel-vasile/mimetype v1.4.3
github.com/trimmer-io/go-xmp v1.0.0
github.com/unidoc/globalsign-dss v0.0.0-20220330092912-b69d85b63736
github.com/unidoc/pkcs7 v0.2.0
github.com/unidoc/unichart v0.3.0
github.com/unidoc/unipdf/v3 v3.55.0
github.com/unidoc/unipdf/v3 v3.57.0
github.com/wcharczuk/go-chart/v2 v2.1.0
golang.org/x/crypto v0.21.0
golang.org/x/crypto v0.22.0
golang.org/x/image v0.15.0
golang.org/x/text v0.14.0
google.golang.org/api v0.114.0
Expand Down Expand Up @@ -51,9 +52,9 @@ require (
github.com/unidoc/timestamp v0.0.0-20200412005513-91597fd3793a // indirect
github.com/unidoc/unitype v0.4.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc v1.56.3 // indirect
Expand Down
Loading

0 comments on commit 8a0f752

Please sign in to comment.