pdf-lib.js.org에서 자세히 알아보세요.
pdf-lib
PDF 조작(특히 PDF 수정 )에 대한 JavaScript 생태계의 강력한 지원 부족을 해결하기 위해 만들어졌습니다.
pdf-lib
의 두 가지 특징은 다음과 같습니다.
사용할 수 있는 다른 좋은 오픈 소스 JavaScript PDF 라이브러리가 있습니다. 그러나 대부분은 문서를 생성 할 수만 있고 기존 문서를 수정할 수는 없습니다. 그리고 이들 중 다수는 특정 환경에서만 작동합니다.
이 예에서는 이 PDF를 생성합니다.
JSFiddle 데모를 사용해 보세요
import { PDFDocument , StandardFonts , rgb } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the Times Roman font
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Get the width and height of the page
const { width , height } = page . getSize ( )
// Draw a string of text toward the top of the page
const fontSize = 30
page . drawText ( 'Creating PDFs in JavaScript is awesome!' , {
x : 50 ,
y : height - 4 * fontSize ,
size : fontSize ,
font : timesRomanFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 (이 PDF가 existingPdfBytes
변수에 사용되는 경우).
JSFiddle 데모를 사용해 보세요
import { degrees , PDFDocument , rgb , StandardFonts } from 'pdf-lib' ;
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...
// Load a PDFDocument from the existing PDF bytes
const pdfDoc = await PDFDocument . load ( existingPdfBytes )
// Embed the Helvetica font
const helveticaFont = await pdfDoc . embedFont ( StandardFonts . Helvetica )
// Get the first page of the document
const pages = pdfDoc . getPages ( )
const firstPage = pages [ 0 ]
// Get the width and height of the first page
const { width , height } = firstPage . getSize ( )
// Draw a string of text diagonally across the first page
firstPage . drawText ( 'This text was added with JavaScript!' , {
x : 5 ,
y : height / 2 + 300 ,
size : 50 ,
font : helveticaFont ,
color : rgb ( 0.95 , 0.1 , 0.1 ) ,
rotate : degrees ( - 45 ) ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다.
JSFiddle 데모를 사용해 보세요
양식 만들기 및 채우기도 참조하세요.
import { PDFDocument } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Add a blank page to the document
const page = pdfDoc . addPage ( [ 550 , 750 ] )
// Get the form so we can add fields to it
const form = pdfDoc . getForm ( )
// Add the superhero text field and description
page . drawText ( 'Enter your favorite superhero:' , { x : 50 , y : 700 , size : 20 } )
const superheroField = form . createTextField ( 'favorite.superhero' )
superheroField . setText ( 'One Punch Man' )
superheroField . addToPage ( page , { x : 55 , y : 640 } )
// Add the rocket radio group, labels, and description
page . drawText ( 'Select your favorite rocket:' , { x : 50 , y : 600 , size : 20 } )
page . drawText ( 'Falcon Heavy' , { x : 120 , y : 560 , size : 18 } )
page . drawText ( 'Saturn IV' , { x : 120 , y : 500 , size : 18 } )
page . drawText ( 'Delta IV Heavy' , { x : 340 , y : 560 , size : 18 } )
page . drawText ( 'Space Launch System' , { x : 340 , y : 500 , size : 18 } )
const rocketField = form . createRadioGroup ( 'favorite.rocket' )
rocketField . addOptionToPage ( 'Falcon Heavy' , page , { x : 55 , y : 540 } )
rocketField . addOptionToPage ( 'Saturn IV' , page , { x : 55 , y : 480 } )
rocketField . addOptionToPage ( 'Delta IV Heavy' , page , { x : 275 , y : 540 } )
rocketField . addOptionToPage ( 'Space Launch System' , page , { x : 275 , y : 480 } )
rocketField . select ( 'Saturn IV' )
// Add the gundam check boxes, labels, and description
page . drawText ( 'Select your favorite gundams:' , { x : 50 , y : 440 , size : 20 } )
page . drawText ( 'Exia' , { x : 120 , y : 400 , size : 18 } )
page . drawText ( 'Kyrios' , { x : 120 , y : 340 , size : 18 } )
page . drawText ( 'Virtue' , { x : 340 , y : 400 , size : 18 } )
page . drawText ( 'Dynames' , { x : 340 , y : 340 , size : 18 } )
const exiaField = form . createCheckBox ( 'gundam.exia' )
const kyriosField = form . createCheckBox ( 'gundam.kyrios' )
const virtueField = form . createCheckBox ( 'gundam.virtue' )
const dynamesField = form . createCheckBox ( 'gundam.dynames' )
exiaField . addToPage ( page , { x : 55 , y : 380 } )
kyriosField . addToPage ( page , { x : 55 , y : 320 } )
virtueField . addToPage ( page , { x : 275 , y : 380 } )
dynamesField . addToPage ( page , { x : 275 , y : 320 } )
exiaField . check ( )
dynamesField . check ( )
// Add the planet dropdown and description
page . drawText ( 'Select your favorite planet*:' , { x : 50 , y : 280 , size : 20 } )
const planetsField = form . createDropdown ( 'favorite.planet' )
planetsField . addOptions ( [ 'Venus' , 'Earth' , 'Mars' , 'Pluto' ] )
planetsField . select ( 'Pluto' )
planetsField . addToPage ( page , { x : 55 , y : 220 } )
// Add the person option list and description
page . drawText ( 'Select your favorite person:' , { x : 50 , y : 180 , size : 18 } )
const personField = form . createOptionList ( 'favorite.person' )
personField . addOptions ( [
'Julius Caesar' ,
'Ada Lovelace' ,
'Cleopatra' ,
'Aaron Burr' ,
'Mark Antony' ,
] )
personField . select ( 'Ada Lovelace' )
personField . addToPage ( page , { x : 55 , y : 70 } )
// Just saying...
page . drawText ( `* Pluto should be a planet too!` , { x : 15 , y : 15 , size : 15 } )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 (이 PDF가 formPdfBytes
변수에 사용될 때 이 이미지는 marioImageBytes
변수에 사용되고 이 이미지는 emblemImageBytes
변수에 사용됩니다).
JSFiddle 데모를 사용해 보세요
양식 만들기 및 채우기도 참조하세요.
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const formPdfBytes = ...
const marioImageBytes = ...
const emblemImageBytes = ...
// Load a PDF with form fields
const pdfDoc = await PDFDocument . load ( formPdfBytes )
// Embed the Mario and emblem images
const marioImage = await pdfDoc . embedPng ( marioImageBytes )
const emblemImage = await pdfDoc . embedPng ( emblemImageBytes )
// Get the form containing all the fields
const form = pdfDoc . getForm ( )
// Get all fields in the PDF by their names
const nameField = form . getTextField ( 'CharacterName 2' )
const ageField = form . getTextField ( 'Age' )
const heightField = form . getTextField ( 'Height' )
const weightField = form . getTextField ( 'Weight' )
const eyesField = form . getTextField ( 'Eyes' )
const skinField = form . getTextField ( 'Skin' )
const hairField = form . getTextField ( 'Hair' )
const alliesField = form . getTextField ( 'Allies' )
const factionField = form . getTextField ( 'FactionName' )
const backstoryField = form . getTextField ( 'Backstory' )
const traitsField = form . getTextField ( 'Feat+Traits' )
const treasureField = form . getTextField ( 'Treasure' )
const characterImageField = form . getButton ( 'CHARACTER IMAGE' )
const factionImageField = form . getTextField ( 'Faction Symbol Image' )
// Fill in the basic info fields
nameField . setText ( 'Mario' )
ageField . setText ( '24 years' )
heightField . setText ( `5' 1"` )
weightField . setText ( '196 lbs' )
eyesField . setText ( 'blue' )
skinField . setText ( 'white' )
hairField . setText ( 'brown' )
// Fill the character image field with our Mario image
characterImageField . setImage ( marioImage )
// Fill in the allies field
alliesField . setText (
[
`Allies:` ,
` • Princess Daisy` ,
` • Princess Peach` ,
` • Rosalina` ,
` • Geno` ,
` • Luigi` ,
` • Donkey Kong` ,
` • Yoshi` ,
` • Diddy Kong` ,
`` ,
`Organizations:` ,
` • Italian Plumbers Association` ,
] . join ( 'n' ) ,
)
// Fill in the faction name field
factionField . setText ( `Mario's Emblem` )
// Fill the faction image field with our emblem image
factionImageField . setImage ( emblemImage )
// Fill in the backstory field
backstoryField . setText (
`Mario is a fictional character in the Mario video game franchise, owned by Nintendo and created by Japanese video game designer Shigeru Miyamoto. Serving as the company's mascot and the eponymous protagonist of the series, Mario has appeared in over 200 video games since his creation. Depicted as a short, pudgy, Italian plumber who resides in the Mushroom Kingdom, his adventures generally center upon rescuing Princess Peach from the Koopa villain Bowser. His younger brother and sidekick is Luigi.` ,
)
// Fill in the traits field
traitsField . setText (
[
`Mario can use three basic three power-ups:` ,
` • the Super Mushroom, which causes Mario to grow larger` ,
` • the Fire Flower, which allows Mario to throw fireballs` ,
` • the Starman, which gives Mario temporary invincibility` ,
] . join ( 'n' ) ,
)
// Fill in the treasure field
treasureField . setText ( [ '• Gold coins' , '• Treasure chests' ] . join ( 'n' ) )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 (이 PDF가 formPdfBytes
변수에 사용되는 경우).
JSFiddle 데모를 사용해 보세요
import { PDFDocument } from 'pdf-lib'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const formPdfBytes = ...
// Load a PDF with form fields
const pdfDoc = await PDFDocument . load ( formPdfBytes )
// Get the form containing all the fields
const form = pdfDoc . getForm ( )
// Fill the form's fields
form . getTextField ( 'Text1' ) . setText ( 'Some Text' ) ;
form . getRadioGroup ( 'Group2' ) . select ( 'Choice1' ) ;
form . getRadioGroup ( 'Group3' ) . select ( 'Choice3' ) ;
form . getRadioGroup ( 'Group4' ) . select ( 'Choice1' ) ;
form . getCheckBox ( 'Check Box3' ) . check ( ) ;
form . getCheckBox ( 'Check Box4' ) . uncheck ( ) ;
form . getDropdown ( 'Dropdown7' ) . select ( 'Infinity' ) ;
form . getOptionList ( 'List Box6' ) . select ( 'Honda' ) ;
// Flatten the form's fields
form . flatten ( ) ;
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 (이 PDF가 firstDonorPdfBytes
변수에 사용되고 이 PDF가 secondDonorPdfBytes
변수에 사용되는 경우).
JSFiddle 데모를 사용해 보세요
import { PDFDocument } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const firstDonorPdfBytes = ...
const secondDonorPdfBytes = ...
// Load a PDFDocument from each of the existing PDFs
const firstDonorPdfDoc = await PDFDocument . load ( firstDonorPdfBytes )
const secondDonorPdfDoc = await PDFDocument . load ( secondDonorPdfBytes )
// Copy the 1st page from the first donor document, and
// the 743rd page from the second donor document
const [ firstDonorPage ] = await pdfDoc . copyPages ( firstDonorPdfDoc , [ 0 ] )
const [ secondDonorPage ] = await pdfDoc . copyPages ( secondDonorPdfDoc , [ 742 ] )
// Add the first copied page
pdfDoc . addPage ( firstDonorPage )
// Insert the second copied page to index 0, so it will be the
// first page in `pdfDoc`
pdfDoc . insertPage ( 0 , secondDonorPage )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 (이 이미지가 jpgImageBytes
변수에 사용되고 이 이미지가 pngImageBytes
변수에 사용되는 경우).
JSFiddle 데모를 사용해 보세요
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const jpgImageBytes = ...
const pngImageBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the JPG image bytes and PNG image bytes
const jpgImage = await pdfDoc . embedJpg ( jpgImageBytes )
const pngImage = await pdfDoc . embedPng ( pngImageBytes )
// Get the width/height of the JPG image scaled down to 25% of its original size
const jpgDims = jpgImage . scale ( 0.25 )
// Get the width/height of the PNG image scaled down to 50% of its original size
const pngDims = pngImage . scale ( 0.5 )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Draw the JPG image in the center of the page
page . drawImage ( jpgImage , {
x : page . getWidth ( ) / 2 - jpgDims . width / 2 ,
y : page . getHeight ( ) / 2 - jpgDims . height / 2 ,
width : jpgDims . width ,
height : jpgDims . height ,
} )
// Draw the PNG image near the lower right corner of the JPG image
page . drawImage ( pngImage , {
x : page . getWidth ( ) / 2 - pngDims . width / 2 + 75 ,
y : page . getHeight ( ) / 2 - pngDims . height ,
width : pngDims . width ,
height : pngDims . height ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 (이 PDF가 americanFlagPdfBytes
변수에 사용되고 이 PDF가 usConstitutionPdfBytes
변수에 사용되는 경우).
JSFiddle 데모를 사용해 보세요
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const americanFlagPdfBytes = ...
const usConstitutionPdfBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the American flag PDF bytes
const [ americanFlag ] = await pdfDoc . embedPdf ( americanFlagPdfBytes )
// Load the U.S. constitution PDF bytes
const usConstitutionPdf = await PDFDocument . load ( usConstitutionPdfBytes )
// Embed the second page of the constitution and clip the preamble
const preamble = await pdfDoc . embedPage ( usConstitutionPdf . getPages ( ) [ 1 ] , {
left : 55 ,
bottom : 485 ,
right : 300 ,
top : 575 ,
} )
// Get the width/height of the American flag PDF scaled down to 30% of
// its original size
const americanFlagDims = americanFlag . scale ( 0.3 )
// Get the width/height of the preamble clipping scaled up to 225% of
// its original size
const preambleDims = preamble . scale ( 2.25 )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Draw the American flag image in the center top of the page
page . drawPage ( americanFlag , {
... americanFlagDims ,
x : page . getWidth ( ) / 2 - americanFlagDims . width / 2 ,
y : page . getHeight ( ) - americanFlagDims . height - 150 ,
} )
// Draw the preamble clipping in the center bottom of the page
page . drawPage ( preamble , {
... preambleDims ,
x : page . getWidth ( ) / 2 - preambleDims . width / 2 ,
y : page . getHeight ( ) / 2 - preambleDims . height / 2 - 50 ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
pdf-lib
사용자 정의 글꼴 포함을 지원하기 위해 자매 모듈인 @pdf-lib/fontkit
사용합니다. 사용자 정의 글꼴을 포함하기 전에 @pdf-lib/fontkit
모듈을 프로젝트에 추가하고 pdfDoc.registerFontkit(...)
사용하여 등록해야 합니다.
@pdf-lib/fontkit
UMD 또는 NPM 모듈로 설치하는 방법에 대한 자세한 설치 지침은 아래를 참조하세요.
이 예에서는 이 PDF를 생성합니다 (이 글꼴이 fontBytes
변수에 사용되는 경우).
JSFiddle 데모를 사용해 보세요
import { PDFDocument , rgb } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If you're running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const fontBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Register the `fontkit` instance
pdfDoc . registerFontkit ( fontkit )
// Embed our custom font in the document
const customFont = await pdfDoc . embedFont ( fontBytes )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Create a string of text and measure its width and height in our custom font
const text = 'This is text in an embedded font!'
const textSize = 35
const textWidth = customFont . widthOfTextAtSize ( text , textSize )
const textHeight = customFont . heightAtSize ( textSize )
// Draw the string of text on the page
page . drawText ( text , {
x : 40 ,
y : 450 ,
size : textSize ,
font : customFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} )
// Draw a box around the string of text
page . drawRectangle ( {
x : 40 ,
y : 450 ,
width : textWidth ,
height : textHeight ,
borderColor : rgb ( 1 , 0 , 0 ) ,
borderWidth : 1.5 ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 (이 이미지가 jpgAttachmentBytes
변수에 사용되고 이 PDF가 pdfAttachmentBytes
변수에 사용되는 경우).
JSFiddle 데모를 사용해 보세요
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const jpgAttachmentBytes = ...
const pdfAttachmentBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Add the JPG attachment
await pdfDoc . attach ( jpgAttachmentBytes , 'cat_riding_unicorn.jpg' , {
mimeType : 'image/jpeg' ,
description : 'Cool cat riding a unicorn! ???️' ,
creationDate : new Date ( '2019/12/01' ) ,
modificationDate : new Date ( '2020/04/19' ) ,
} )
// Add the PDF attachment
await pdfDoc . attach ( pdfAttachmentBytes , 'us_constitution.pdf' , {
mimeType : 'application/pdf' ,
description : 'Constitution of the United States ???' ,
creationDate : new Date ( '1787/09/17' ) ,
modificationDate : new Date ( '1992/05/07' ) ,
} )
// Add a page with some text
const page = pdfDoc . addPage ( ) ;
page . drawText ( 'This PDF has two attachments' , { x : 135 , y : 415 } )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
이 예에서는 이 PDF를 생성합니다 .
JSFiddle 데모를 사용해 보세요
import { PDFDocument , StandardFonts } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the Times Roman font
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman )
// Add a page and draw some text on it
const page = pdfDoc . addPage ( [ 500 , 600 ] )
page . setFont ( timesRomanFont )
page . drawText ( 'The Life of an Egg' , { x : 60 , y : 500 , size : 50 } )
page . drawText ( 'An Epic Tale of Woe' , { x : 125 , y : 460 , size : 25 } )
// Set all available metadata fields on the PDFDocument. Note that these fields
// are visible in the "Document Properties" section of most PDF readers.
pdfDoc . setTitle ( '? The Life of an Egg ?' )
pdfDoc . setAuthor ( 'Humpty Dumpty' )
pdfDoc . setSubject ( ' An Epic Tale of Woe ' )
pdfDoc . setKeywords ( [ 'eggs' , 'wall' , 'fall' , 'king' , 'horses' , 'men' ] )
pdfDoc . setProducer ( 'PDF App 9000 ?' )
pdfDoc . setCreator ( 'pdf-lib (https://github.com/Hopding/pdf-lib)' )
pdfDoc . setCreationDate ( new Date ( '2018-06-24T01:58:37.228Z' ) )
pdfDoc . setModificationDate ( new Date ( '2019-12-21T07:00:11.000Z' ) )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
JSFiddle 데모를 사용해 보세요
import { PDFDocument } from 'pdf-lib'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...
// Load a PDFDocument without updating its existing metadata
const pdfDoc = await PDFDocument . load ( existingPdfBytes , {
updateMetadata : false
} )
// Print all available metadata fields
console . log ( 'Title:' , pdfDoc . getTitle ( ) )
console . log ( 'Author:' , pdfDoc . getAuthor ( ) )
console . log ( 'Subject:' , pdfDoc . getSubject ( ) )
console . log ( 'Creator:' , pdfDoc . getCreator ( ) )
console . log ( 'Keywords:' , pdfDoc . getKeywords ( ) )
console . log ( 'Producer:' , pdfDoc . getProducer ( ) )
console . log ( 'Creation Date:' , pdfDoc . getCreationDate ( ) )
console . log ( 'Modification Date:' , pdfDoc . getModificationDate ( ) )
이 스크립트는 다음을 출력합니다( 이 PDF가 existingPdfBytes
변수에 사용되는 경우 ).
Title: Microsoft Word - Basic Curriculum Vitae example.doc
Author: Administrator
Subject: undefined
Creator: PScript5.dll Version 5.2
Keywords: undefined
Producer: Acrobat Distiller 8.1.0 (Windows)
Creation Date: 2010-07-29T14:26:00.000Z
Modification Date: 2010-07-29T14:26:00.000Z
import {
PDFDocument ,
StandardFonts ,
NonFullScreenPageMode ,
ReadingDirection ,
PrintScaling ,
Duplex ,
PDFName ,
} from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the Times Roman font
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman )
// Add a page and draw some text on it
const page = pdfDoc . addPage ( [ 500 , 600 ] )
page . setFont ( timesRomanFont )
page . drawText ( 'The Life of an Egg' , { x : 60 , y : 500 , size : 50 } )
page . drawText ( 'An Epic Tale of Woe' , { x : 125 , y : 460 , size : 25 } )
// Set all available viewer preferences on the PDFDocument:
const viewerPrefs = pdfDoc . catalog . getOrCreateViewerPreferences ( )
viewerPrefs . setHideToolbar ( true )
viewerPrefs . setHideMenubar ( true )
viewerPrefs . setHideWindowUI ( true )
viewerPrefs . setFitWindow ( true )
viewerPrefs . setCenterWindow ( true )
viewerPrefs . setDisplayDocTitle ( true )
// Set the PageMode (otherwise setting NonFullScreenPageMode has no meaning)
pdfDoc . catalog . set ( PDFName . of ( 'PageMode' ) , PDFName . of ( 'FullScreen' ) )
// Set what happens when fullScreen is closed
viewerPrefs . setNonFullScreenPageMode ( NonFullScreenPageMode . UseOutlines )
viewerPrefs . setReadingDirection ( ReadingDirection . L2R )
viewerPrefs . setPrintScaling ( PrintScaling . None )
viewerPrefs . setDuplex ( Duplex . DuplexFlipLongEdge )
viewerPrefs . setPickTrayByPDFSize ( true )
// We can set the default print range to only the first page
viewerPrefs . setPrintPageRange ( { start : 0 , end : 0 } )
// Or we can supply noncontiguous ranges (e.g. pages 1, 3, and 5-7)
viewerPrefs . setPrintPageRange ( [
{ start : 0 , end : 0 } ,
{ start : 2 , end : 2 } ,
{ start : 4 , end : 6 } ,
] )
viewerPrefs . setNumCopies ( 2 )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
import { PDFDocument } from 'pdf-lib'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...
// Load a PDFDocument without updating its existing metadata
const pdfDoc = await PDFDocument . load ( existingPdfBytes )
const viewerPrefs = pdfDoc . catalog . getOrCreateViewerPreferences ( )
// Print all available viewer preference fields
console . log ( 'HideToolbar:' , viewerPrefs . getHideToolbar ( ) )
console . log ( 'HideMenubar:' , viewerPrefs . getHideMenubar ( ) )
console . log ( 'HideWindowUI:' , viewerPrefs . getHideWindowUI ( ) )
console . log ( 'FitWindow:' , viewerPrefs . getFitWindow ( ) )
console . log ( 'CenterWindow:' , viewerPrefs . getCenterWindow ( ) )
console . log ( 'DisplayDocTitle:' , viewerPrefs . getDisplayDocTitle ( ) )
console . log ( 'NonFullScreenPageMode:' , viewerPrefs . getNonFullScreenPageMode ( ) )
console . log ( 'ReadingDirection:' , viewerPrefs . getReadingDirection ( ) )
console . log ( 'PrintScaling:' , viewerPrefs . getPrintScaling ( ) )
console . log ( 'Duplex:' , viewerPrefs . getDuplex ( ) )
console . log ( 'PickTrayByPDFSize:' , viewerPrefs . getPickTrayByPDFSize ( ) )
console . log ( 'PrintPageRange:' , viewerPrefs . getPrintPageRange ( ) )
console . log ( 'NumCopies:' , viewerPrefs . getNumCopies ( ) )
이 스크립트는 다음을 출력합니다( 이 PDF가 existingPdfBytes
변수에 사용되는 경우 ).
HideToolbar: true
HideMenubar: true
HideWindowUI: false
FitWindow: true
CenterWindow: true
DisplayDocTitle: true
NonFullScreenPageMode: UseNone
ReadingDirection: R2L
PrintScaling: None
Duplex: DuplexFlipLongEdge
PickTrayByPDFSize: true
PrintPageRange: [ { start: 1, end: 1 }, { start: 3, end: 4 } ]
NumCopies: 2
이 예에서는 이 PDF를 생성합니다 .
JSFiddle 데모를 사용해 보세요
import { PDFDocument , rgb } from 'pdf-lib'
// SVG path for a wavy line
const svgPath =
'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
page . moveTo ( 100 , page . getHeight ( ) - 5 )
// Draw the SVG path as a black line
page . moveDown ( 25 )
page . drawSvgPath ( svgPath )
// Draw the SVG path as a thick green line
page . moveDown ( 200 )
page . drawSvgPath ( svgPath , { borderColor : rgb ( 0 , 1 , 0 ) , borderWidth : 5 } )
// Draw the SVG path and fill it with red
page . moveDown ( 200 )
page . drawSvgPath ( svgPath , { color : rgb ( 1 , 0 , 0 ) } )
// Draw the SVG path at 50% of its original size
page . moveDown ( 200 )
page . drawSvgPath ( svgPath , { scale : 0.5 } )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
pdf-lib
흥미롭고 새로운 Deno 런타임을 완벽하게 지원합니다! 모든 사용 예제는 Deno에서 작동합니다. 당신이 해야 할 유일한 일은 Skypack CDN을 사용하기 위해 pdf-lib
및 @pdf-lib/fontkit
에 대한 가져오기를 변경하는 것입니다. Deno에서는 URL을 통해 모든 모듈을 참조해야 하기 때문입니다.
pdf-lib를 사용하여 Deno에서 PDF 파일을 만들고 수정하는 방법도 참조하세요.
다음은 Deno용으로 수정된 문서 생성 예입니다.
import {
PDFDocument ,
StandardFonts ,
rgb ,
} from 'https://cdn.skypack.dev/pdf-lib@^1.11.1?dts' ;
const pdfDoc = await PDFDocument . create ( ) ;
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman ) ;
const page = pdfDoc . addPage ( ) ;
const { width , height } = page . getSize ( ) ;
const fontSize = 30 ;
page . drawText ( 'Creating PDFs in JavaScript is awesome!' , {
x : 50 ,
y : height - 4 * fontSize ,
size : fontSize ,
font : timesRomanFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} ) ;
const pdfBytes = await pdfDoc . save ( ) ;
await Deno . writeFile ( 'out.pdf' , pdfBytes ) ;
이 스크립트를 create-document.ts
로 저장하면 Deno에서 다음 명령을 사용하여 실행할 수 있습니다.
deno run --allow-write create-document.ts
결과 out.pdf
파일은 다음 PDF와 같습니다.
다음은 Deno에 글꼴을 삽입하고 텍스트를 측정하는 방법을 보여주는 약간 더 복잡한 예입니다.
import {
degrees ,
PDFDocument ,
rgb ,
StandardFonts ,
} from 'https://cdn.skypack.dev/pdf-lib@^1.11.1?dts' ;
import fontkit from 'https://cdn.skypack.dev/@pdf-lib/fontkit@^1.0.0?dts' ;
const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf' ;
const fontBytes = await fetch ( url ) . then ( ( res ) => res . arrayBuffer ( ) ) ;
const pdfDoc = await PDFDocument . create ( ) ;
pdfDoc . registerFontkit ( fontkit ) ;
const customFont = await pdfDoc . embedFont ( fontBytes ) ;
const page = pdfDoc . addPage ( ) ;
const text = 'This is text in an embedded font!' ;
const textSize = 35 ;
const textWidth = customFont . widthOfTextAtSize ( text , textSize ) ;
const textHeight = customFont . heightAtSize ( textSize ) ;
page . drawText ( text , {
x : 40 ,
y : 450 ,
size : textSize ,
font : customFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} ) ;
page . drawRectangle ( {
x : 40 ,
y : 450 ,
width : textWidth ,
height : textHeight ,
borderColor : rgb ( 1 , 0 , 0 ) ,
borderWidth : 1.5 ,
} ) ;
const pdfBytes = await pdfDoc . save ( ) ;
await Deno . writeFile ( 'out.pdf' , pdfBytes ) ;
이 스크립트를 custom-font.ts
로 저장하면 다음 명령을 사용하여 실행할 수 있습니다.
deno run --allow-write --allow-net custom-font.ts
결과 out.pdf
파일은 다음 PDF와 같습니다.
사용 예제에서는 pdf-lib
의 다양한 기능을 보여주는 간단하고 명확한 코드를 제공합니다. apps/
디렉터리에서 전체 작업 예제를 찾을 수 있습니다. 이러한 앱은 모든 릴리스 전에(자동 테스트 외에도) pdf-lib
수동으로 테스트하는 데 사용됩니다.
현재 4개의 앱이 있습니다:
node
- Node 환경의 pdf-lib
에 대한 테스트가 포함되어 있습니다. 이 테스트는 파일 시스템에서 pdf-lib
사용하여 PDF, 글꼴 또는 이미지를 저장/로드하려고 할 때 편리한 참조입니다. 또한 호환성을 보장하기 위해 다양한 뷰어(Acrobat, Preview, Foxit, Chrome, Firefox 등)에서 PDF를 빠르게 열 수 있습니다.web
- 브라우저 환경에서 pdf-lib
에 대한 테스트가 포함되어 있습니다. 이 테스트는 브라우저 환경에서 pdf-lib
사용하여 PDF, 글꼴 또는 이미지를 저장/로드하려고 할 때 편리한 참고 자료입니다.rn
- React Native 환경의 pdf-lib
에 대한 테스트가 포함되어 있습니다. 이 테스트는 React Native 환경에서 pdf-lib
사용하여 PDF, 글꼴 또는 이미지를 저장/로드하려고 할 때 편리한 참조입니다.deno
- Deno 환경의 pdf-lib
에 대한 테스트가 포함되어 있습니다. 이 테스트는 파일 시스템에서 pdf-lib
사용하여 PDF, 글꼴 또는 이미지를 저장/로드하려고 할 때 편리한 참조입니다. 최신 안정 버전을 설치하려면:
# With npm
npm install --save pdf-lib
# With yarn
yarn add pdf-lib
이는 패키지 관리자로 npm 또는 Yarn을 사용한다고 가정합니다.
unpkg 또는 jsDelivr에서 pdf-lib
UMD 모듈로 다운로드할 수도 있습니다. UMD 빌드는 ES5로 컴파일되었으므로 모든 최신 브라우저에서 작동합니다. UMD 빌드는 패키지 관리자나 모듈 번들러를 사용하지 않는 경우 유용합니다. 예를 들어 HTML 페이지의 <script>
태그에서 직접 사용할 수 있습니다.
다음 빌드를 사용할 수 있습니다.
참고: 프로덕션에서 CDN 스크립트를 사용하는 경우 URL에 특정 버전 번호를 포함해야 합니다. 예:
- https://unpkg.com/[email protected]/dist/pdf-lib.min.js
- https://cdn.jsdelivr.net/npm/[email protected]/dist/pdf-lib.min.js
UMD 빌드를 사용하면 전역 window.PDFLib
변수에 액세스할 수 있습니다. 이 변수에는 pdf-lib
에서 내보낸 모든 클래스와 함수가 포함됩니다. 예를 들어:
// NPM module
import { PDFDocument , rgb } from 'pdf-lib' ;
// UMD module
var PDFDocument = PDFLib . PDFDocument ;
var rgb = PDFLib . rgb ;
pdf-lib
사용자 정의 글꼴 포함을 지원하기 위해 자매 모듈인 @pdf-lib/fontkit
사용합니다. 사용자 정의 글꼴을 포함하기 전에 @pdf-lib/fontkit
모듈을 프로젝트에 추가하고 pdfDoc.registerFontkit(...)
사용하여 등록해야 합니다(글꼴 포함 예제 참조). 이 모듈은 모든 사용자에게 필요하지 않고 번들 크기가 늘어나므로 기본적으로 포함되지 않습니다.
이 모듈을 설치하는 것은 쉽습니다. pdf-lib
자체와 마찬가지로 @pdf-lib/fontkit
npm
/ yarn
사용하거나 UMD 모듈로 설치할 수 있습니다.
# With npm
npm install --save @pdf-lib/fontkit
# With yarn
yarn add @pdf-lib/fontkit
fontkit
인스턴스를 등록하려면 다음을 수행하세요.
import { PDFDocument } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'
const pdfDoc = await PDFDocument . create ( )
pdfDoc . registerFontkit ( fontkit )
다음 빌드를 사용할 수 있습니다.
참고: 프로덕션에서 CDN 스크립트를 사용하는 경우 URL에 특정 버전 번호를 포함해야 합니다. 예:
- https://unpkg.com/@pdf-lib/[email protected]/dist/fontkit.umd.min.js
- https://cdn.jsdelivr.net/npm/@pdf-lib/[email protected]/dist/fontkit.umd.min.js
UMD 빌드를 사용하면 전역 window.fontkit
변수에 액세스할 수 있습니다. fontkit
인스턴스를 등록하려면 다음을 수행하세요.
var pdfDoc = await PDFLib . PDFDocument . create ( )
pdfDoc . registerFontkit ( fontkit )
API 문서는 프로젝트 사이트 https://pdf-lib.js.org/docs/api/에서 확인할 수 있습니다.
프로젝트 사이트(및 생성된 문서 파일)의 저장소는 https://github.com/Hopding/pdf-lib-docs에 있습니다.
PDF 작업을 할 때 "문자 인코딩"과 "글꼴"이라는 용어를 자주 접하게 됩니다. 웹 개발 경험이 있다면 이것이 왜 그렇게 널리 퍼져 있는지 궁금할 것입니다. 걱정할 필요가 없는 성가신 세부 사항이 아닌가요? PDF 라이브러리와 리더가 웹 브라우저처럼 이 모든 것을 처리할 수 있어야 하지 않습니까? 불행하게도 그렇지 않습니다. PDF 파일 형식의 특성상 PDF 작업 시 문자 인코딩과 글꼴을 고려하지 않기가 매우 어렵습니다.
pdf-lib
작업을 단순화하기 위해 최선을 다합니다. 하지만 마법을 행할 수는 없습니다. 즉, 다음 사항을 알고 있어야 합니다.
import { PDFDocument , StandardFonts } from 'pdf-lib'
const pdfDoc = await PDFDocument . create ( )
const courierFont = await pdfDoc . embedFont ( StandardFonts . Courier )
const page = pdfDoc . addPage ( )
page . drawText ( 'Some boring latin text in the Courier font' , {
font : courierFont ,
} )
embedFont
메서드에 전달해야 합니다. 고유한 글꼴을 포함하면 해당 글꼴이 지원하는 모든 유니코드 문자를 사용할 수 있습니다. 이 기능을 사용하면 표준 글꼴에 따른 제한 사항에서 벗어날 수 있습니다. 대부분의 PDF 파일은 포함된 글꼴을 사용합니다. 다음과 같이 사용자 정의 글꼴을 포함하고 사용할 수 있습니다(참조). import { PDFDocument } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'
const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf'
const fontBytes = await fetch ( url ) . then ( ( res ) => res . arrayBuffer ( ) )
const pdfDoc = await PDFDocument . create ( )
pdfDoc . registerFontkit ( fontkit )
const ubuntuFont = await pdfDoc . embedFont ( fontBytes )
const page = pdfDoc . addPage ( )
page . drawText ( 'Some fancy Unicode text in the ŪЬȕǹƚü font' , {
font : ubuntuFont ,
} )
지원하지 않는 글꼴이 포함된 문자를 사용하려고 하면 인코딩 오류가 발생합니다. 예를 들어, Ω
WinAnsi 문자 집합에 없습니다. 따라서 표준 Helvetica 글꼴을 사용하여 페이지에 그리려고 하면 다음 오류가 발생합니다.
Error: WinAnsi cannot encode "Ω" (0x03a9)
at Encoding.encodeUnicodeCodePoint
PDF 문서에 글꼴을 포함하면 일반적으로 파일 크기가 늘어납니다. 필요한 문자만 포함되도록 글꼴을 하위 설정하면 파일 크기가 늘어나는 정도를 줄일 수 있습니다. subset
옵션을 true
로 설정하여 글꼴을 하위 집합으로 설정할 수 있습니다. 예를 들어:
const font = await pdfDoc . embedFont ( fontBytes , { subset : true } ) ;
하위 설정은 모든 글꼴에 대해 작동하지 않습니다. 자세한 내용은 #207(설명)을 참조하세요.
pdf-lib
PDF 양식 필드를 만들고, 채우고, 읽을 수 있습니다. 다음 필드 유형이 지원됩니다.
코드 샘플은 양식 생성 및 양식 채우기 사용 예를 참조하세요. 전체 예제의 테스트 1, 14, 15, 16 및 17에는 다양한 JS 환경에서 양식 생성 및 채우기를 위한 작업 예제 코드가 포함되어 있습니다.
중요: 버튼, 드롭다운, 옵션 목록 및 텍스트 필드에 텍스트를 표시하는 데 사용되는 기본 글꼴은 표준 Helvetica 글꼴입니다. 이 글꼴은 라틴 알파벳 문자만 지원합니다(자세한 내용은 글꼴 및 유니코드 참조). 이는 라틴 알파벳 이외의 텍스트를 포함하도록 이러한 필드 유형이 생성되거나 수정되는 경우(종종 그렇듯이) 사용자 정의 글꼴을 포함하고 사용하여 필드 모양을 업데이트해야 함을 의미합니다. 그렇지 않으면 오류가 발생합니다(아마도 PDFDocument
를 저장할 때).
다음과 같이 양식 필드를 채울 때 포함된 글꼴을 사용할 수 있습니다.
import { PDFDocument } from 'pdf-lib' ;
import fontkit from '@pdf-lib/fontkit' ;
// Fetch the PDF with form fields
const formUrl = 'https://pdf-lib.js.org/assets/dod_character.pdf' ;
const formBytes = await fetch ( formUrl ) . then ( ( res ) => res . arrayBuffer ( ) ) ;
// Fetch the Ubuntu font
const fontUrl = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf' ;
const fontBytes = await fetch ( fontUrl ) . then ( ( res ) => res . arrayBuffer ( ) ) ;
// Load the PDF with form fields
const pdfDoc = await PDFDocument . load ( formBytes ) ;
// Embed the Ubuntu font
pdfDoc . registerFontkit ( fontkit ) ;
const ubuntuFont = await pdfDoc . embedFont ( fontBytes ) ;
// Get two text fields from the form
const form = pdfDoc . getForm ( ) ;
const nameField = form . getTextField ( 'CharacterName 2' ) ;
const ageField = form . getTextField ( 'Age' ) ;
// Fill the text fields with some fancy Unicode characters (outside
// the WinAnsi latin character set)
nameField . setText ( 'Ӎӑȑїõ' ) ;
ageField . setText ( '24 ŷȇȁŗš' ) ;
// **Key Step:** Update the field appearances with the Ubuntu font
form . updateFieldAppearances ( ubuntuFont ) ;
// Save the PDF with filled form fields
const pdfBytes = await pdfDoc . save ( ) ;
기존 양식 필드는 PDFForm
의 다음 방법을 사용하여 액세스할 수 있습니다.
PDFForm.getButton
PDFForm.getCheckBox
PDFForm.getDropdown
PDFForm.getOptionList
PDFForm.getRadioGroup
PDFForm.getTextField
PDFForm
의 다음 방법을 사용하여 새 양식 필드를 만들 수 있습니다.
PDFForm.createButton
PDFForm.createCheckBox
PDFForm.createDropdown
PDFForm.createOptionList
PDFForm.createRadioGroup
PDFForm.createTextField
다음은 앞서 언급한 PDFField
의 하위 클래스를 읽고 채우는 데 가장 일반적으로 사용되는 방법 중 일부입니다.
PDFCheckBox.check
PDFCheckBox.uncheck
PDFCheckBox.isChecked
PDFDropdown.select
PDFDropdown.clear
PDFDropdown.getSelected
PDFDropdown.getOptions
PDFDropdown.addOptions
PDFOptionList.select
PDFOptionList.clear
PDFOptionList.getSelected
PDFOptionList.getOptions
PDFOptionList.addOptions
PDFRadioGroup.select
PDFRadioGroup.clear
PDFRadioGroup.getSelected
PDFRadioGroup.getOptions
PDFRadioGroup.addOptionToPage
PDFTextField.setText
PDFTextField.getText
PDFTextField.setMaxLength
PDFTextField.getMaxLength
PDFTextField.removeMaxLength
pdf-lib
텍스트 필드의 내용을 추출 할 수 있지만 ( PDFTextField.getText
참조) 양식 필드 외부 페이지의 일반 텍스트는 추출 할 수 없습니다 . 이는 구현하기 어려운 기능이지만 이 라이브러리의 범위 내에 있으며 향후 pdf-lib
에 추가될 수 있습니다. #93, #137, #177, #329, #380을 참조하세요.pdf-lib
텍스트 필드의 내용을 제거하고 편집 할 수 있지만 ( PDFTextField.setText
참조) 양식 필드 외부의 페이지에서 텍스트를 제거하거나 편집하기 위한 API를 제공하지 않습니다 . 이 기능 역시 구현하기 어려운 기능이지만 pdf-lib
범위 내에 있으며 향후 추가될 수 있습니다. #93, #137, #177, #329, #380을 참조하세요.pdf-lib
PDF에 내용을 추가할 때 HTML 또는 CSS 사용을 지원하지 않습니다 . 마찬가지로 pdf-lib
HTML/CSS 콘텐츠를 PDF에 포함 할 수 없습니다 . 이러한 기능은 편리할 수 있지만 구현하기가 매우 어렵고 이 라이브러리의 범위를 훨씬 벗어납니다. 이 기능이 필요한 경우 Puppeteer 사용을 고려해보세요. 토론은 우리와 채팅하고, 질문하고, pdf-lib에 대해 자세히 알아볼 수 있는 최고의 장소입니다!
MAINTAINERSHIP.md#communication 및 MAINTAINERSHIP.md#discord도 참조하세요.
pdf-lib
현재 암호화된 문서를 지원하지 않습니다. 암호화된 문서에는 pdf-lib
사용하면 안 됩니다. 하지만 이는 pdf-lib
에 추가할 수 있는 기능입니다. 이 기능이 도움이 된다면 이슈를 만들어주세요!
암호화된 문서가 PDFDocument.load(...)
에 전달되면 오류가 발생합니다.
import { PDFDocument , EncryptedPDFError } from 'pdf-lib'
const encryptedPdfBytes = ...
// Assignment fails. Throws an `EncryptedPDFError`.
const pdfDoc = PDFDocument . load ( encryptedPdfBytes )
이 기본 동작은 일반적으로 원하는 것입니다. 이를 통해 특정 문서가 암호화되었는지 쉽게 감지할 수 있으며 문서를 수정하려는 시도를 방지할 수 있습니다. 그러나 실제로 문서를 로드하려면 { ignoreEncryption: true }
옵션을 사용할 수 있습니다.
import { PDFDocument } from 'pdf-lib'
const encryptedPdfBytes = ...
// Assignment succeeds. Does not throw an error.
const pdfDoc = PDFDocument . load ( encryptedPdfBytes , { ignoreEncryption : true } )
이 옵션을 사용해도 문서의 암호가 해독되지는 않습니다 . 이는 반환된 PDFDocument
에 대해 수정을 시도하면 실패하거나 예상치 못한 결과가 발생할 수 있음을 의미합니다.
이 옵션을 사용하면 안 됩니다. 이전 버전과의 호환성을 위해서만 존재합니다.
우리는 오픈 소스 커뮤니티의 기여를 환영합니다! pdf-lib
에 기여하고 싶다면 CONTRIBUTING.md 파일을 살펴보세요. 여기에는 pdf-lib
설정하고 컴퓨터에서 실행하는 데 도움이 되는 정보가 포함되어 있습니다. (최대한 간단하고 빠르게 만들려고 노력하고 있습니다!)
이 저장소가 유지 관리되는 방법과 문제, PR 및 토론을 사용하는 방법에 대한 자세한 내용은 MAINTAINERSHIP.md를 확인하세요.
pdfkit
노드 및 브라우저용 PDF 생성 라이브러리입니다. 이 라이브러리는 pdf-lib
생성할 때 참조 및 존재 증명으로 매우 도움이 되었습니다. 글꼴 포함, PNG 포함, JPG 포함을 위한 pdfkit
의 코드가 특히 유용했습니다.pdf.js
브라우저용 PDF 렌더링 라이브러리입니다. 이 라이브러리는 pdf-lib
의 파서를 작성할 때 참고 자료로 도움이 되었습니다. 스트림 디코딩을 위한 코드 중 일부는 pdf-lib
에서 사용하기 위해 TypeScript로 직접 포팅되었습니다.pdfbox
Java로 작성된 PDF 생성 및 수정 라이브러리입니다. 이 라이브러리는 양식 생성을 구현하고 pdf-lib
용 API를 채울 때 귀중한 참조였습니다.jspdf
브라우저용 PDF 생성 라이브러리입니다.pdfmake
브라우저용 PDF 생성 라이브러리입니다.hummus
Node 환경을 위한 PDF 생성 및 수정 라이브러리입니다. hummus
C++ 라이브러리를 둘러싼 노드 래퍼이므로 브라우저나 React Native와 같은 많은 JavaScript 환경에서는 작동하지 않습니다.react-native-pdf-lib
는 React Native 환경을 위한 PDF 생성 및 수정 라이브러리입니다. react-native-pdf-lib
C++ 및 Java 라이브러리를 둘러싼 래퍼입니다.pdfassembler
는 Node와 브라우저를 위한 PDF 생성 및 수정 라이브러리입니다. 사용하려면 PDF 문서의 논리적 구조에 대한 지식이 필요합니다. 이 저장소에는 루트 디렉터리에 pdf_specification.pdf
라는 파일이 포함되어 있었습니다. 이는 Adobe에서 무료로 제공하는 PDF 1.7 사양의 복사본입니다. 2021년 8월 30일에 우리는 이 저장소에서 파일을 제거하라는 DMCA 신고서를 접수했습니다. master
에 대한 새로운 커밋을 통해 파일을 제거하는 것만으로는 불만 사항을 만족시키기에 충분하지 않았습니다. 해당 파일은 저장소의 Git 기록에서 완전히 제거되어야 했습니다. 불행하게도 이 파일은 2년 전에 추가되었습니다. 이는 저장소의 Git 기록을 다시 작성하고 master
로 푸시를 강제해야 함을 의미합니다.
여기에 설명된 대로 BFG Repo-Cleaner를 사용하여 파일을 제거하고 리포지토리 기록을 다시 작성했습니다. 완전한 투명성을 위해 우리가 실행한 정확한 명령은 다음과 같습니다.
$ git clone [email protected]:Hopding/pdf-lib.git
$ cd pdf-lib
$ rm pdf_specification.pdf
$ git commit -am 'Remove pdf_specification.pdf'
$ bfg --delete-files pdf_specification.pdf
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git push --force
당신이 pdf-lib
사용자라면 신경쓰지 않아도 됩니다! 평소처럼 pdf-lib
계속 사용하시겠습니까? !
귀하가 pdf-lib
개발자라면( pdf-lib
포크했거나 공개 PR을 갖고 있음을 의미함) 이는 귀하에게 영향을 미칩니다. 2021년 8월 30일 이전에 저장소를 포크하거나 복제한 경우 포크의 git 기록이 이 저장소의 master
브랜치와 동기화되지 않습니다. 불행하게도 이것은 당신이 처리해야 할 골치 아픈 일이 될 것입니다. 죄송합니다! 우리는 역사를 다시 쓰고 싶지 않았지만 실제로는 대안이 없었습니다.
pdf-lib의 소스 코드가 전혀 변경되지 않았다는 점에 유의하는 것이 중요합니다. git 히스토리를 다시 작성하기 전과 똑같습니다. 리포지토리에는 여전히 정확히 동일한 수의 커밋이 있습니다(그리고 pdf_specification.pdf
추가한 커밋을 제외하고 동일한 커밋 내용도 포함됩니다). 변경된 것은 해당 커밋의 SHA입니다.
이 사실을 처리하는 가장 간단한 방법은 다음과 같습니다.
Git 기록 재작성에 수반되는 내용에 대한 훌륭하고 심층적인 설명은 이 StackOverflow 답변을 참조하세요.
MIT