github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/create.go (about) 1 /* 2 Copyright 2019 The pdfcpu Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package api 18 19 import ( 20 "io" 21 "os" 22 23 "github.com/pdfcpu/pdfcpu/pkg/log" 24 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 25 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/create" 26 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 27 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types" 28 "github.com/pkg/errors" 29 ) 30 31 // CreatePDFFile creates a PDF file for an xRefTable and writes it to outFile. 32 func CreatePDFFile(xRefTable *model.XRefTable, outFile string, conf *model.Configuration) error { 33 f, err := os.Create(outFile) 34 if err != nil { 35 return err 36 } 37 defer f.Close() 38 ctx := pdfcpu.CreateContext(xRefTable, conf) 39 return WriteContext(ctx, f) 40 } 41 42 // Create renders the PDF structure represented by rs into w. 43 // If rs is present, new PDF content will be appended including any empty pages needed. 44 // rd is a JSON representation of PDF page content which may include form data. 45 func Create(rs io.ReadSeeker, rd io.Reader, w io.Writer, conf *model.Configuration) error { 46 if rd == nil { 47 return errors.New("pdfcpu: Create: missing rd") 48 } 49 50 if conf == nil { 51 conf = model.NewDefaultConfiguration() 52 } 53 conf.Cmd = model.CREATE 54 55 var ( 56 ctx *model.Context 57 err error 58 ) 59 60 if rs != nil { 61 ctx, err = ReadValidateAndOptimize(rs, conf) 62 } else { 63 ctx, err = pdfcpu.CreateContextWithXRefTable(conf, types.PaperSize["A4"]) 64 } 65 if err != nil { 66 return err 67 } 68 69 if err := create.FromJSON(ctx, rd); err != nil { 70 return err 71 } 72 73 if conf.PostProcessValidate { 74 if err = ValidateContext(ctx); err != nil { 75 return err 76 } 77 } 78 79 return WriteContext(ctx, w) 80 } 81 82 func handleOutFilePDF(inFilePDF, outFilePDF string, tmpFile *string) { 83 if outFilePDF != "" && inFilePDF != outFilePDF { 84 *tmpFile = outFilePDF 85 logWritingTo(outFilePDF) 86 } else { 87 logWritingTo(inFilePDF) 88 } 89 } 90 91 // CreateFile renders the PDF structure represented by inFileJSON into outFilePDF. 92 // If inFilePDF is present, new PDF content will be appended including any empty pages needed. 93 // inFileJSON represents PDF page content which may include form data. 94 func CreateFile(inFilePDF, inFileJSON, outFilePDF string, conf *model.Configuration) (err error) { 95 var f0, f1, f2 *os.File 96 97 if f0, err = os.Open(inFileJSON); err != nil { 98 return err 99 } 100 101 rs := io.ReadSeeker(nil) 102 f1 = nil 103 if fileExists(inFilePDF) { 104 if f1, err = os.Open(inFilePDF); err != nil { 105 return err 106 } 107 log.CLI.Printf("reading %s...\n", inFilePDF) 108 rs = f1 109 } 110 111 tmpFile := inFilePDF + ".tmp" 112 handleOutFilePDF(inFilePDF, outFilePDF, &tmpFile) 113 114 if f2, err = os.Create(tmpFile); err != nil { 115 return err 116 } 117 118 defer func() { 119 if err != nil { 120 f2.Close() 121 if f1 != nil { 122 f1.Close() 123 } 124 f0.Close() 125 os.Remove(tmpFile) 126 return 127 } 128 if err = f2.Close(); err != nil { 129 return 130 } 131 if f1 != nil { 132 if err = f1.Close(); err != nil { 133 return 134 } 135 } 136 if err = f0.Close(); err != nil { 137 return 138 } 139 if outFilePDF == "" || inFilePDF == outFilePDF { 140 err = os.Rename(tmpFile, inFilePDF) 141 } 142 }() 143 144 return Create(rs, f0, f2, conf) 145 }