尝试首先 footer/header 隐藏 Puppeteer 生成的 PDF
Trying to hide first footer/header on PDF generated with Puppeteer
我是 nodejs 函数的新手,也是 puppeteer。以前我用的是 wkhtmltopdf 但目前它的选项很差。
所以,我的想法是从 html 生成带有首页封面(完整 A4 width/height 的图像)的 pdf,因为页脚是从 index.js 生成的, 无法将其隐藏在 PDF 的第一页。
//Imports
const puppeteer = require('puppeteer');
//Open browser
async function startBrowser() {
const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']});
const page = await browser.newPage();
return {browser, page};
}
//Close browser
async function closeBrowser(browser) {
return browser.close();
}
//Html to pdf
async function html2pdf(url) {
const {browser, page} = await startBrowser();
await page.goto(url, {waitUntil: 'networkidle2'});
await page.emulateMedia('screen');
//Options
await page.pdf({
printBackground: true,
path: 'result.pdf',
displayHeaderFooter: true,
footerTemplate: '<div style="width:100%;text-align:right;position:relative;top:10px;right:10px;"><img width="60px" src="data:data:image/..."'
margin : {top: '0px',right: '0px',bottom: '40px',left: '0px' },
scale: 1,
landscape: false,
format: 'A4',
pageRanges: ""
});
}
//Exec
(async () => {
await html2pdf('file:///loc/node_pdfs/givenhtml.html');
process.exit(1);
})();
我的问题是,有什么方法可以找到第一个页脚并将其隐藏在索引函数中吗?
谢谢!
目前有多个错误(请参阅 this question/answer or this one)导致无法正常工作。
目前只有 headers 使用此技巧(取自此 github comment)才有可能:
await page.addStyleTag({
content: `
body { margin-top: 1cm; }
@page:first { margin-top: 0; }
`,
});
这基本上会隐藏第一页的页边距,但在使用底部页边距时不起作用(如 here 所述)。
可能的解决方案
我推荐的解决方案是创建两个 PDF,一个只有第一页且没有边距,另一个有剩余页面和边距:
await page.pdf({
displayHeaderFooter: false,
pageRanges: '1',
path: 'page1.pdf',
});
await page.pdf({
displayHeaderFooter: true,
footerTemplate: '<div style="font-size:5mm;">Your footer text</div>',
margin: {
bottom: '10mm'
},
pageRanges: '2-', // start this PDF at page 2
path: 'remaining-pages.pdf',
});
根据您需要执行任务的频率,您可以手动合并 PDF 或使用 easy-pdf-merge(我自己没有使用过这个)之类的工具自动合并。
小提示:easy-pdf-merge
一个pdf-merge
有一些"system-tools-dependencies"
我更喜欢 pdf-lib
,一个可以使用缓冲区和 Typescript 支持的普通 js 工具
我的打字稿:
import {PDFDocument} from 'pdf-lib'
...
const options: PDFOptions = {
format: 'A4',
displayHeaderFooter: true,
footerTemplate: footerTemplate,
margin: {
top: '20mm',
bottom: '20mm',
},
}
const page1: Buffer = await page.pdf({
...options,
headerTemplate: '<div><!-- no header hack --></div>',
pageRanges: '1',
})
const page2: Buffer = await page.pdf({
...options,
headerTemplate: headerTemplate,
pageRanges: '2-',
})
const pdfDoc = await PDFDocument.create()
const coverDoc = await PDFDocument.load(page1)
const [coverPage] = await pdfDoc.copyPages(coverDoc, [0])
pdfDoc.addPage(coverPage)
const mainDoc = await PDFDocument.load(page2)
for (let i = 0; i < mainDoc.getPageCount(); i++) {
const [aMainPage] = await pdfDoc.copyPages(mainDoc, [i])
pdfDoc.addPage(aMainPage)
}
const pdfBytes = await pdfDoc.save()
// Buffer for https response in my case
return Buffer.from(pdfBytes)
...
我是 nodejs 函数的新手,也是 puppeteer。以前我用的是 wkhtmltopdf 但目前它的选项很差。
所以,我的想法是从 html 生成带有首页封面(完整 A4 width/height 的图像)的 pdf,因为页脚是从 index.js 生成的, 无法将其隐藏在 PDF 的第一页。
//Imports
const puppeteer = require('puppeteer');
//Open browser
async function startBrowser() {
const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']});
const page = await browser.newPage();
return {browser, page};
}
//Close browser
async function closeBrowser(browser) {
return browser.close();
}
//Html to pdf
async function html2pdf(url) {
const {browser, page} = await startBrowser();
await page.goto(url, {waitUntil: 'networkidle2'});
await page.emulateMedia('screen');
//Options
await page.pdf({
printBackground: true,
path: 'result.pdf',
displayHeaderFooter: true,
footerTemplate: '<div style="width:100%;text-align:right;position:relative;top:10px;right:10px;"><img width="60px" src="data:data:image/..."'
margin : {top: '0px',right: '0px',bottom: '40px',left: '0px' },
scale: 1,
landscape: false,
format: 'A4',
pageRanges: ""
});
}
//Exec
(async () => {
await html2pdf('file:///loc/node_pdfs/givenhtml.html');
process.exit(1);
})();
我的问题是,有什么方法可以找到第一个页脚并将其隐藏在索引函数中吗?
谢谢!
目前有多个错误(请参阅 this question/answer or this one)导致无法正常工作。
目前只有 headers 使用此技巧(取自此 github comment)才有可能:
await page.addStyleTag({
content: `
body { margin-top: 1cm; }
@page:first { margin-top: 0; }
`,
});
这基本上会隐藏第一页的页边距,但在使用底部页边距时不起作用(如 here 所述)。
可能的解决方案
我推荐的解决方案是创建两个 PDF,一个只有第一页且没有边距,另一个有剩余页面和边距:
await page.pdf({
displayHeaderFooter: false,
pageRanges: '1',
path: 'page1.pdf',
});
await page.pdf({
displayHeaderFooter: true,
footerTemplate: '<div style="font-size:5mm;">Your footer text</div>',
margin: {
bottom: '10mm'
},
pageRanges: '2-', // start this PDF at page 2
path: 'remaining-pages.pdf',
});
根据您需要执行任务的频率,您可以手动合并 PDF 或使用 easy-pdf-merge(我自己没有使用过这个)之类的工具自动合并。
小提示:easy-pdf-merge
一个pdf-merge
有一些"system-tools-dependencies"
我更喜欢 pdf-lib
,一个可以使用缓冲区和 Typescript 支持的普通 js 工具
我的打字稿:
import {PDFDocument} from 'pdf-lib'
...
const options: PDFOptions = {
format: 'A4',
displayHeaderFooter: true,
footerTemplate: footerTemplate,
margin: {
top: '20mm',
bottom: '20mm',
},
}
const page1: Buffer = await page.pdf({
...options,
headerTemplate: '<div><!-- no header hack --></div>',
pageRanges: '1',
})
const page2: Buffer = await page.pdf({
...options,
headerTemplate: headerTemplate,
pageRanges: '2-',
})
const pdfDoc = await PDFDocument.create()
const coverDoc = await PDFDocument.load(page1)
const [coverPage] = await pdfDoc.copyPages(coverDoc, [0])
pdfDoc.addPage(coverPage)
const mainDoc = await PDFDocument.load(page2)
for (let i = 0; i < mainDoc.getPageCount(); i++) {
const [aMainPage] = await pdfDoc.copyPages(mainDoc, [i])
pdfDoc.addPage(aMainPage)
}
const pdfBytes = await pdfDoc.save()
// Buffer for https response in my case
return Buffer.from(pdfBytes)
...