Created
August 6, 2020 14:21
-
-
Save AZagatti/736d5be318a299e95daef2d423e4c0b8 to your computer and use it in GitHub Desktop.
PDF
This file contains hidden or 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
import PDFDocument from 'pdfkit'; | |
import { | |
copyFileSync, | |
createWriteStream, | |
existsSync, | |
mkdirSync, | |
readdirSync, | |
readFileSync, | |
statSync, | |
watchFile, | |
unwatchFile, | |
} from 'fs'; | |
import { join } from 'path'; | |
import { toDataURL } from 'qrcode'; | |
import shortid from 'shortid'; | |
import rimraf from 'rimraf'; | |
import { promisify } from 'util'; | |
import { exec } from 'child_process'; | |
import { log, warn } from 'console'; | |
import crypto from 'crypto'; | |
import accents from 'remove-accents'; | |
import { rejects } from 'assert'; | |
import { prototype } from 'events'; | |
const shellExec = promisify(exec); | |
const debug = false; | |
shortid.characters( | |
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_', | |
); | |
interface IFullPath { | |
files: string; | |
images: string; | |
outPut: string; | |
tempFile: string; | |
endFile: string; | |
} | |
interface IParams { | |
company: string | null; | |
margin: number | null; | |
custom: { | |
qrCode: { | |
size: number | null; | |
position: | |
| 'top-left' | |
| 'top-right' | |
| 'bottom-left' | |
| 'bottom-right' | |
| null; | |
}; | |
signature: { | |
position: | |
| 'top-left' | |
| 'top-right' | |
| 'bottom-left' | |
| 'bottom-right' | |
| null; | |
}; | |
logo: { | |
sizeMultiplier: number | null; | |
opacity: number | null; | |
visible: boolean | null; | |
position: | |
| 'top-left' | |
| 'top-right' | |
| 'bottom-left' | |
| 'bottom-right' | |
| null; | |
}; | |
}; | |
} | |
interface IDocumentoPDFSerialized { | |
data: Date; | |
nomeArquivo: string; | |
tamanho: number; | |
idDocumento: string; | |
idPaginas: any; | |
caminhos: { | |
arquivo: string; | |
pasta: string; | |
}; | |
sha1Hash: string; | |
} | |
interface IDocumentoPDF { | |
uniqueFolder: string; | |
filesPath: string | null; | |
imagesPath: string | null; | |
outPutPath: string | null; | |
companyName: string; | |
companyNameFileName: string; | |
logoTipo: Buffer; | |
customFont: string; | |
uuid1: string; | |
outPutName: string; | |
fullPath: IFullPath; | |
preDoc: PDFKit.PDFDocument; | |
finalDoc: PDFKit.PDFDocument; | |
currentDate: string; | |
retorno: IDocumentoPDFSerialized; | |
} | |
class DocumentoPDF implements IDocumentoPDF { | |
public static normalId(size: number = 8) { | |
let id = shortid.generate().substr(0, size); | |
const lenDiff = size - id.length; | |
if (lenDiff) { | |
for (let i = 0; i < lenDiff; i += 1) { | |
id += String(Math.round(Math.random() * 9)); | |
} | |
} | |
return id; | |
} | |
public static gerarHash(chave: string, dados: string[]) { | |
if (!chave || !dados || !dados.length) { | |
throw new Error('Não foi possível gerar hash.'); | |
} | |
const hash = crypto | |
.createHmac('sha1', chave) | |
.update(dados.join('')) | |
.digest('hex'); | |
if (debug) { | |
log(chave, dados.join(''), hash); | |
} | |
return hash; | |
} | |
public uniqueFolder: string; | |
public filesPath: string | null; | |
public imagesPath: string | null; | |
public outPutPath: string | null; | |
public params: IParams | null; | |
public companyName: string; | |
public companyNameFileName: string; | |
public logoTipo: Buffer; | |
public customFont: string; | |
public uuid1: string; | |
public outPutName: string; | |
public fullPath: IFullPath; | |
public preDoc: PDFKit.PDFDocument; | |
public finalDoc: PDFKit.PDFDocument; | |
public currentDate: string; | |
public retorno: IDocumentoPDFSerialized; | |
constructor( | |
uniqueFolder = '', | |
params = null, | |
filesPath = null, | |
imagesPath = null, | |
outPutPath = null, | |
) { | |
if (!process.env.PDFAUTH_HASH_KEY || !process.env.API_URL) { | |
throw new Error( | |
'Não foi possível verificar dados necessários ao gerador.', | |
); | |
} | |
this.uniqueFolder = uniqueFolder; | |
if (!uniqueFolder) { | |
throw new Error('Pasta única obrigatória.'); | |
} | |
this.filesPath = | |
filesPath || join(__dirname, '../../public/documentopdf/files/'); | |
this.imagesPath = | |
imagesPath || join(__dirname, '../../public/documentopdf/images/'); | |
this.outPutPath = | |
outPutPath || join(__dirname, '../../public/documentopdf/output/'); | |
this.params = params; | |
this.companyName = this.params!.company || 'Analise Já'; | |
this.companyNameFileName = accents( | |
this.companyName.toLowerCase().replace(/\s/g, ''), | |
); | |
this.logoTipo = readFileSync( | |
join(__dirname, '../../public/documentopdf/logo.png'), | |
); | |
this.customFont = join(__dirname, '../../public/documentopdf/Symtext.ttf'); | |
this.uuid1 = DocumentoPDF.normalId(); | |
this.outPutName = `${this.companyNameFileName}.${this.uuid1}.pdf`; | |
this.fullPath = { | |
files: join(this.filesPath, this.uniqueFolder), | |
images: join(this.imagesPath, this.uniqueFolder), | |
outPut: join(this.outPutPath, this.uniqueFolder), | |
tempFile: join( | |
this.outPutPath, | |
this.uniqueFolder, | |
`temp_${this.outPutName}`, | |
), | |
endFile: join(this.outPutPath, this.uniqueFolder, this.outPutName), | |
}; | |
this.preDoc = new PDFDocument({ | |
autoFirstPage: false, | |
compress: true, | |
}); | |
this.finalDoc = new PDFDocument({ | |
autoFirstPage: false, | |
// userPassword: "1234", | |
compress: true, | |
ownerPassword: DocumentoPDF.gerarHash(process.env.PDFAUTH_HASH_KEY!, [ | |
this.uuid1!, | |
]), | |
permissions: { | |
printing: 'highResolution', | |
fillingForms: false, | |
modifying: false, | |
copying: false, | |
annotating: false, | |
contentAccessibility: false, | |
documentAssembly: false, | |
}, | |
// layout: "portrait", // podeser 'landscape' - horizontal | |
info: { | |
Title: `${this.companyName} - ${this.uuid1}`, | |
Author: `${this.companyName}`, // Autor | |
// Subject: "", // Assunto | |
// Keywords: "pdf;javascript", // Palavras-chave | |
// CreationDate:'DD/MM/YYYY', // Data de criação (é gerada automaticamento caso n seja setada) | |
// ModDate: "DD/MM/YYYY" // Data de modificação | |
}, | |
}); | |
this.currentDate = new Date().toLocaleString(); | |
this.retorno = { | |
data: new Date(), | |
nomeArquivo: '', | |
tamanho: 0, | |
idDocumento: '', | |
idPaginas: [{}], | |
caminhos: { | |
arquivo: '', | |
pasta: '', | |
}, | |
sha1Hash: '', | |
}; | |
} | |
public async gerarPastas() { | |
try { | |
// Gerando /files | |
if (!existsSync(this.filesPath!)) { | |
mkdirSync(this.filesPath!); | |
throw new Error( | |
'Gerando `/files`, pasta vazia. Preencha a pasta e reinicie o processo.', | |
); | |
} | |
if (!existsSync(this.fullPath.files)) { | |
throw new Error('Pasta única inexistente.'); | |
return true; | |
} | |
// Gerando /images | |
if (!existsSync(this.imagesPath!)) { | |
if (debug) { | |
warn('Gerando /images'); | |
} | |
mkdirSync(this.imagesPath!); | |
} | |
if (!existsSync(this.fullPath.images)) { | |
if (debug) { | |
warn('Gerando /images'); | |
} | |
mkdirSync(this.fullPath.images); | |
} | |
// Gerando /output | |
if (!existsSync(this.outPutPath!)) { | |
if (debug) { | |
warn('Gerando /output'); | |
} | |
mkdirSync(this.outPutPath!); | |
} | |
// Gerando /output/unique | |
if (!existsSync(this.fullPath.outPut)) { | |
if (debug) { | |
warn('Gerando /output'); | |
} | |
mkdirSync(this.fullPath.outPut); | |
} | |
} catch (error) { | |
throw new Error(error); | |
} | |
} | |
public async converterPDFs( | |
files: string[], | |
folderWrapper: string | null = null, | |
) { | |
try { | |
// Converter imagens | |
return Promise.all( | |
files.map( | |
(file: any): Promise<any> => | |
new Promise( | |
async (resolve, reject): Promise<boolean | any> => { | |
try { | |
if (file.endsWith('.pdf')) { | |
if (debug) { | |
log( | |
`Convertendo pdf: ${folderWrapper || | |
this.fullPath.files}${file}`, | |
); | |
} | |
const { stdout, stderr } = await shellExec( | |
`pdftoppm ${folderWrapper || | |
this.fullPath.files}${file} ${ | |
this.fullPath.images | |
}${file.replace('.pdf', '')} -png -r 250`, | |
); | |
if (stderr) { | |
throw new Error(stderr); | |
} | |
if (debug) { | |
log(`stdout: ${stdout}`); | |
log('Arquivo convertido.'); | |
} | |
} else if ( | |
file.endsWith('.png') || | |
file.endsWith('.jpg') || | |
file.endsWith('.jpeg') | |
) { | |
if (debug) { | |
log( | |
`Copiando imagem existente: ${this.fullPath.files}${file}`, | |
); | |
} | |
copyFileSync( | |
`${this.fullPath.files}${file}`, | |
`${this.fullPath.images}${file}`, | |
); | |
} | |
resolve(true); | |
} catch (err) { | |
reject(err); | |
} | |
}, | |
), | |
), | |
); | |
} catch (error) { | |
throw new Error(error); | |
} | |
} | |
public async desenharPDF(prop: any, images: string[], i: number) { | |
try { | |
const uuid2 = DocumentoPDF.normalId(); | |
prop.pages.push({ | |
uuid2, | |
sha1Hash: DocumentoPDF.gerarHash(process.env.PDFAUTH_HASH_KEY!, [ | |
this.uuid1, | |
uuid2, | |
]), | |
}); | |
const qrCodeImage = await toDataURL(`${this.uuid1}/${uuid2}`); | |
if (debug) { | |
log('Gerando página, id:', this.uuid1, uuid2); | |
} | |
// gerar página, adicionar imagem | |
this.preDoc | |
.addPage({ | |
size: [prop.width, prop.height], | |
margin: 0, | |
}) | |
.image( | |
`${this.fullPath.images}${images[i]}`, | |
prop.relX(0), | |
prop.relX(0), | |
{ | |
fit: [prop.relX(100) - prop.relX(0), prop.relY(100) - prop.relY(0)], | |
align: 'center', | |
valign: 'center', | |
}, | |
) | |
.save(); | |
// debug | |
// this.preDoc | |
// .rect(0, 0, prop.width, prop.height) | |
// .fill('#C60') | |
// .restore() | |
// .save(); | |
// colocar marca d´agua | |
const uuid1Label = Array.from(this.uuid1).join('\n'); | |
const uuid2Label = Array.from(uuid2).join('\n'); | |
const waterMarkLineGap = 6.4; | |
this.preDoc | |
.fillOpacity(0.1) | |
.lineWidth(prop.area(0.75)) | |
.strokeOpacity(0.1) | |
.fillAndStroke('#000', '#FFF') | |
.font('Helvetica') | |
.fontSize(prop.area(30)) | |
.text(uuid1Label, prop.relX(0), prop.relY(0), { | |
width: prop.relX(100) - prop.relX(0), | |
height: prop.relY(100), | |
lineGap: -prop.area(waterMarkLineGap), | |
fill: true, | |
stroke: true, | |
columns: 2, | |
columnGap: 0, | |
}) | |
.save() | |
.rotate(180) | |
.text(uuid2Label, -prop.relX(100), -prop.relY(100), { | |
width: prop.relX(100) - prop.relX(0), | |
height: prop.relY(100), | |
lineGap: -prop.area(waterMarkLineGap), | |
fill: true, | |
stroke: true, | |
columns: 2, | |
columnGap: prop.area(1), | |
}) | |
.restore() | |
.save(); | |
if (prop.custom.signature.visible) { | |
// referenciar autenticação | |
const autenticLabel = `Documento autenticado por ${this.companyName} em ${this.currentDate}`; | |
this.preDoc | |
.font('Times-Bold') | |
.rotate(-90) | |
.fontSize(prop.area(1)) | |
.fillOpacity(0.5) | |
.rect( | |
-prop.filtrarY( | |
prop.custom.signature.position, | |
this.preDoc.widthOfString(autenticLabel), | |
), | |
prop.filtrarX( | |
prop.custom.signature.position, | |
this.preDoc.heightOfString(autenticLabel), | |
), | |
this.preDoc.widthOfString(autenticLabel), | |
this.preDoc.heightOfString(autenticLabel), | |
) | |
.fill('#FFF') | |
.fillOpacity(1) | |
.fill('#333') | |
.text( | |
autenticLabel, | |
-prop.filtrarY( | |
prop.custom.signature.position, | |
this.preDoc.widthOfString(autenticLabel), | |
), | |
prop.filtrarX( | |
prop.custom.signature.position, | |
this.preDoc.heightOfString(autenticLabel), | |
), | |
{ | |
align: 'left', | |
width: prop.relY(100) - prop.relY(0), | |
}, | |
) | |
// .fontSize(prop.area(1.6)) | |
// .text(`${this.uuid1} ${uuid2}`, -prop.relX(41.55), prop.relY(68), { | |
// align: 'right', | |
// width: prop.relY(28.5), | |
// }) | |
.restore() | |
.save(); | |
} | |
// assinar referencia do documento, no topo | |
const topRefLabel = `${this.uuid1} ${new Date().getTime()}`; | |
this.preDoc | |
.fontSize(prop.area(1)) | |
.fillOpacity(0.5) | |
.rect( | |
prop.relX(50) - this.preDoc.widthOfString(topRefLabel) / 2, | |
prop.relY(0), | |
this.preDoc.widthOfString(topRefLabel), | |
this.preDoc.heightOfString(topRefLabel), | |
) | |
.fill('#FFF') | |
.fillOpacity(1) | |
.fill('#333') | |
.text(topRefLabel, prop.relX(0), prop.relY(0.1), { | |
align: 'center', | |
width: prop.relX(100) - prop.relX(0), | |
}) | |
.save(); | |
// assinar referencia da pagina, à esquerda | |
const leftRefLabel = `${uuid2} ${new Date().getTime()}`; | |
this.preDoc | |
.rotate(90) | |
.fontSize(prop.area(1)) | |
.fillOpacity(0.5) | |
.rect( | |
prop.relY(50) - this.preDoc.widthOfString(leftRefLabel) / 2, | |
-prop.relX(0) - prop.area(1), | |
this.preDoc.widthOfString(leftRefLabel), | |
this.preDoc.heightOfString(leftRefLabel), | |
) | |
.fill('#FFF') | |
.fillOpacity(1) | |
.fill('#333') | |
.text(leftRefLabel, prop.relY(0), -prop.relX(0) - prop.area(0.9), { | |
align: 'center', | |
width: prop.relY(100) - prop.relY(0), | |
}) | |
.restore() | |
.save(); | |
// Numerar páginas, com margem para o qrCode | |
if (prop.custom.qrCode.visible) { | |
const qrCodeSize = prop.area(prop.custom.qrCode.size); | |
const paginationLabel = `${i + 1}/${images.length}`; | |
this.preDoc | |
.fontSize(prop.area(1)) | |
.fillOpacity(0.5) | |
.rect( | |
prop.filtrarX( | |
prop.custom.qrCode.position, | |
this.preDoc.widthOfString(paginationLabel), | |
), | |
prop.filtrarY( | |
prop.custom.qrCode.position, | |
qrCodeSize - prop.margin, | |
qrCodeSize + | |
this.preDoc.heightOfString(paginationLabel) - | |
prop.margin, | |
), | |
this.preDoc.widthOfString(paginationLabel), | |
this.preDoc.heightOfString(paginationLabel), | |
) | |
.fill('#FFF') | |
.fillOpacity(1) | |
.fill('#333') | |
.text( | |
paginationLabel, | |
prop.filtrarX( | |
prop.custom.qrCode.position, | |
this.preDoc.widthOfString(paginationLabel), | |
), | |
prop.filtrarY( | |
prop.custom.qrCode.position, | |
qrCodeSize - prop.margin, | |
qrCodeSize + | |
this.preDoc.heightOfString(paginationLabel) - | |
prop.margin, | |
), | |
{ | |
align: 'left', | |
width: qrCodeSize, | |
fill: true, | |
}, | |
) | |
.save(); | |
// colocar o qrCode | |
this.preDoc | |
.fillOpacity(1) | |
.image( | |
Buffer.from( | |
qrCodeImage.replace('data:image/png;base64,', ''), | |
'base64', | |
), | |
prop.filtrarX( | |
prop.custom.qrCode.position, | |
qrCodeSize - prop.margin, | |
), | |
prop.filtrarY( | |
prop.custom.qrCode.position, | |
0, | |
qrCodeSize - prop.margin, | |
), | |
{ | |
width: qrCodeSize - prop.relX(0), | |
height: qrCodeSize - prop.relX(0), | |
}, | |
) | |
.save(); | |
} | |
if (prop.custom.logo.visible) { | |
// colocar logotipo | |
this.preDoc | |
.fillOpacity(prop.custom.logo.opacity) | |
.rect( | |
prop.filtrarX(prop.custom.logo.position, prop.custom.logo.width()), | |
prop.filtrarY( | |
prop.custom.logo.position, | |
0, | |
prop.custom.logo.height(), | |
), | |
prop.custom.logo.width(), | |
prop.custom.logo.height(), | |
) | |
.fill('#FFF') | |
.image( | |
this.logoTipo, | |
prop.filtrarX(prop.custom.logo.position, prop.custom.logo.width()), | |
prop.filtrarY( | |
prop.custom.logo.position, | |
0, | |
prop.custom.logo.height(), | |
), | |
{ | |
width: prop.custom.logo.width(), | |
height: prop.custom.logo.height(), | |
}, | |
) | |
.save(); | |
} | |
// borda traçado | |
this.preDoc | |
.rect( | |
prop.relX(0) - prop.area(0.1), | |
prop.relY(0) - prop.area(0.1), | |
prop.relX(100) - prop.relX(0) + prop.area(0.1), | |
prop.relY(100) - prop.relY(0) + prop.area(0.1), | |
) | |
.lineWidth(prop.area(0.1)) | |
.strokeColor('#000') | |
.strokeOpacity(0.25) | |
.dash(prop.area(0.4), { space: prop.area(0.3) }) | |
.stroke() | |
.restore() | |
.save(); | |
} catch (error) { | |
throw new Error(error); | |
} | |
} | |
public async gerarPDFAutenticado() { | |
try { | |
await this.gerarPastas(); | |
// Ler pasta unica de arquivos | |
const files = readdirSync(this.fullPath.files); | |
if (!files.length) { | |
if (debug) { | |
warn( | |
'Nenhum arquivo encontrado em /files. Preencha a pasta e reinicie o processo.', | |
); | |
} | |
return true; | |
} | |
if (debug) { | |
log( | |
`\n\rConvertendo PDFs para imagens, pasta:\n\r${this.filesPath}\n\r`, | |
); | |
} | |
// Converter arquivos da pasta /files/:unique | |
await this.converterPDFs(files); | |
// Definir propriedades do documento | |
const prop = { | |
width: 595, | |
height: 842, | |
margin: this.params!.margin || 25, | |
custom: { | |
qrCode: { | |
size: this.params!.custom?.qrCode?.size || 10, | |
visible: true, | |
position: this.params!.custom?.qrCode?.position || 'bottom-left', | |
}, | |
signature: { | |
visible: true, | |
position: | |
this.params!.custom?.signature?.position || 'bottom-right', | |
}, | |
logo: { | |
sizeMultiplier: this.params!.custom?.logo?.sizeMultiplier || 0.4, | |
width: () => 512 * prop.custom?.logo?.sizeMultiplier, | |
height: () => 83 * prop.custom?.logo?.sizeMultiplier, | |
opacity: this.params!.custom?.logo?.opacity || 0.5, | |
visible: true, | |
position: this.params!.custom?.logo?.position || 'top-left', | |
}, | |
}, | |
withMargin: { | |
vertical: () => prop.width - 2 * prop.margin, | |
horizontal: () => prop.height - 2 * prop.margin, | |
}, | |
relX: (percent: number) => | |
prop.margin + | |
Math.round((percent * prop.withMargin.vertical()) / 100), | |
relY: (percent: number) => | |
prop.margin + | |
Math.round((percent * prop.withMargin.horizontal()) / 100), | |
area: (percent: number) => | |
Math.round( | |
(percent * Math.sqrt(prop.relX(100) * prop.relY(100))) / 100, | |
), | |
pages: [] as any[], | |
filtrarX: ( | |
location: string, | |
rightOffset: number = 0, | |
leftOffset: number = 0, | |
) => { | |
const map: any = { | |
'top-right': prop.relX(100) - rightOffset, | |
'top-left': prop.relX(0) + leftOffset, | |
'bottom-left': prop.relX(0) + leftOffset, | |
'bottom-right': prop.relX(100) - rightOffset, | |
// tslint:disable-next-line: object-literal-key-quotes | |
default: prop.relX(0), | |
}; | |
return map[location] || map.default; | |
}, | |
filtrarY: ( | |
location: string, | |
upOffset: number = 0, | |
downOffset: number = 0, | |
) => { | |
const map: any = { | |
'top-right': prop.relY(0) + upOffset, | |
'top-left': prop.relY(0) + upOffset, | |
'bottom-left': prop.relY(100) - downOffset, | |
'bottom-right': prop.relY(100) - downOffset, | |
// tslint:disable-next-line: object-literal-key-quotes | |
default: prop.relY(0), | |
}; | |
return map[location] || map.default; | |
}, | |
}; | |
// Ler pasta images/:unique | |
const images = readdirSync(this.fullPath.images); | |
if (debug) { | |
log( | |
`\n\rGerando um PDF a partir das imagens da pasta temporária:\n\r${this.fullPath.images}\n\r`, | |
); | |
} | |
// Definindo stream 'temp' | |
this.preDoc.pipe(createWriteStream(this.fullPath.tempFile)); | |
// Desenhando PDF | |
for (let i = 0; i < images.length; i++) { | |
// for (let i = 0; i < 1; i++) { | |
if ( | |
images[i].endsWith('.png') || | |
images[i].endsWith('.jpg') || | |
images[i].endsWith('.jpeg') | |
) { | |
if (debug) { | |
log(`Referência: ${this.fullPath.images}${images[i]}`); | |
} | |
await this.desenharPDF(prop, images, i); | |
} | |
} | |
this.preDoc.end(); | |
return new Promise((resolve, reject) => { | |
watchFile(this.fullPath.tempFile, async (event) => { | |
try { | |
if (event) { | |
unwatchFile(this.fullPath.tempFile); | |
await this.gerarPDFImagens(prop); | |
resolve(true); | |
} | |
throw new Error('Não foi possível gerar o PDF'); | |
} catch (error) { | |
reject(error); | |
} | |
}); | |
}); | |
} catch (error) { | |
rimraf.sync(this.fullPath.files); | |
rimraf.sync(this.fullPath.images); | |
rimraf.sync(this.fullPath.outPut); | |
if (debug) { | |
warn('\n\rArquivo deletado:', this.fullPath.endFile); | |
warn('\n\rPasta deletada:', this.fullPath.files); | |
warn('\n\rPasta deletada:', this.fullPath.images); | |
warn('\n\rPasta deletada:', this.fullPath.outPut); | |
} | |
throw new Error(error); | |
} | |
} | |
public async gerarPDFImagens(prop: any) { | |
try { | |
rimraf.sync(this.fullPath.files); | |
rimraf.sync(this.fullPath.images); | |
if (!existsSync(this.fullPath.images)) { | |
if (debug) { | |
warn('Deletando e recriando', this.fullPath.images); | |
} | |
mkdirSync(this.fullPath.images); | |
} | |
if (debug) { | |
warn('\n\rPasta deletada:', this.fullPath.files); | |
warn('\n\rPasta recriada:', this.fullPath.images); | |
log('\n\rGerado em:', this.fullPath.tempFile); | |
} | |
const tempFile = readdirSync(this.fullPath.outPut); | |
if (!tempFile.length) { | |
if (debug) { | |
warn( | |
`Nenhum arquivo encontrado em ${this.fullPath.outPut}. Ocorreu algum erro.`, | |
); | |
} | |
return true; | |
} | |
if (debug) { | |
log( | |
`\n\rConvertendo PDFs para imagens, pasta:\n\r${this.fullPath.outPut}\n\r`, | |
); | |
} | |
await this.converterPDFs(tempFile, this.fullPath.outPut); | |
const images = readdirSync(this.fullPath.images); | |
if (debug) { | |
log( | |
`\n\rGerando um PDF a partir das imagens da pasta temporária:\n\r${this.fullPath.images}\n\r`, | |
); | |
} | |
// Definindo stream final | |
this.finalDoc.pipe(createWriteStream(this.fullPath.endFile)); | |
// Desenhando PDF Final | |
for (const image of images) { | |
if ( | |
image.endsWith('.png') || | |
image.endsWith('.jpg') || | |
image.endsWith('.jpeg') | |
) { | |
if (debug) { | |
log(`Referência: ${this.fullPath.images}${image}`); | |
} | |
this.finalDoc | |
.addPage({ | |
size: [prop.width, prop.height], | |
margin: 0, | |
}) | |
.image(`${this.fullPath.images}${image}`, 0, 0, { | |
fit: [prop.width, prop.height], | |
align: 'center', | |
valign: 'center', | |
}) | |
.save(); | |
} | |
} | |
this.finalDoc.end(); | |
return new Promise((resolve, reject) => { | |
watchFile(this.fullPath.endFile, async (event) => { | |
if (event) { | |
try { | |
unwatchFile(this.fullPath.endFile); | |
rimraf.sync(this.fullPath.images); | |
if (debug) { | |
warn('\n\rPasta deletada:', this.fullPath.images); | |
log('\n\rGerado em:', this.fullPath.endFile); | |
} | |
const sha1Hash = DocumentoPDF.gerarHash( | |
process.env.PDFAUTH_HASH_KEY!, | |
[this.uuid1, ...prop.pages.map((el: any) => el.uuid2)], | |
); | |
this.retorno = { | |
data: new Date(), | |
nomeArquivo: this.outPutName, | |
tamanho: statSync(this.fullPath.endFile).size, | |
idDocumento: this.uuid1, | |
idPaginas: prop.pages, | |
caminhos: { | |
arquivo: this.fullPath.endFile, | |
pasta: this.fullPath.outPut, | |
}, | |
sha1Hash, | |
}; | |
resolve(true); | |
} catch (error) { | |
reject(error); | |
} | |
} | |
}); | |
}); | |
} catch (error) { | |
throw new Error(error); | |
} | |
} | |
public serialize(): IDocumentoPDFSerialized { | |
return this.retorno; | |
} | |
} | |
export { DocumentoPDF, IDocumentoPDFSerialized }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment