Html2pdf.js 前端畫面轉 PDF 並用 ajax 傳送

平民百姓
7 min readJan 8, 2021

--

html2pdf 官方文件內容實在是太少了,看完了還是一頭霧水
參考了多人的代碼並且在實作的過程中踩了一堆坑
趕緊紀錄一下避免以後忘了又要重踩一次

程式流程

async function transfer() {
await changeHtmlTagsIntoSpan()
await cutPage()
let doc if (頁數 > 5) {
doc = await renderLargePdf()
} else {
doc = await renderPdf()
}
sendPdf(doc)
}

PDF頁數 <= 5

async function renderPdf() {  opt = {
margin: 10,
pagebreak: { before:['.page-break'], avoid: 'img' },
filename: 'test.pdf',
jsPDF: { format: 'a4', orientation: 'portrait' },
html2canvas: {
scale: 2,
useCORS: true, // 沒有的話轉成PDF後所有的<img>內容都會不見
}
}
let content = document.getElementById('body') let doc = await html2pdf()
.from(content)
.set(opt)
.toPdf()
.get('pdf')
.then(function (pdf) {
let totalPages = pdf.internal.getNumberOfPages()
let onePageHeight = pdf.internal.pageSize.getHeight()
let onePageWidth = pdf.internal.pageSize.getWidth()
// 這邊使用google的開源中文字,不然原本html2pdf不支援UTF-8中文輸出
pdf.addFileToVFS('TaipeiSansTCBeta-normal', TaipeiSansTCBeta);
pdf.addFont('TaipeiSansTCBeta-normal', 'TaipeiSansTCBeta', 'normal');
// 添加完後必須 Set
pdf.setFont('TaipeiSansTCBeta');
pdf.setFontSize(16)
pdf.setTextColor('red')
// 讀取每頁設定頁尾
for (let page = 1; i <= totalPages; i++) {
pdf.setPage(page)
pdf.text(page, 15, onePageHeight - 10)
pdf.text(date(), onePageWidth - 50, onePageHeight - 10)
}
return pdf
})
return doc
}

PDF 頁數 > 5 (因 canvas 長度有限制,所以轉成PDF後內容會消失)

function renderLargePdf() {  // 這邊是重點, 直接寫死單頁canvas高度、寬度
let opt = {
margin: 10,
pagebreak: { before:['.page-break'], avoid: 'img' },
filename: filename,
html2canvas: {
scale: 2, // 清楚程度
letterRendering: true,
width: $('body').width(), // canvas 寬度, 視情況調整
height: 1480, // canvas 單頁高度, 請自行調整
useCORS: true, // 可顯示跨域圖片
},
jsPDF: {
format: 'a4',
orientation: 'portrait'
},
}
let onePageElements = document.getElementsByClassName('one-page')
let totalPages = onePageElements.length
let onePageHeight = pdf.internal.pageSize.getHeight()
var doc = html2pdf() for (let page = 0; page < totalPages; page++) {
doc = doc.set(opt)
.from(onePageElements[page])
.toContainer()
.toCanvas()
.toPdf()
.get('pdf')
.then(pdf => {
... pdf.text('I am footer', 100, onePageHeight - 10) // 最後一頁後不用再新增一頁
if (page < (totalPages - 1)) pdf.addPage()
})
return doc.get('pdf')
}
}

Ajax 傳送 pdf

function sendPdf(pdf) {
$.ajax({
type: 'POST',
datatype: 'JSON',
data: { pdf: btoa(pdf.output()) }, // 重點是要 pdf.output()
success: function (res) {},
error: function () {}
})
}

--

--

平民百姓
平民百姓

Written by 平民百姓

由後端轉全端的弱弱工程師 - 生活筆記

No responses yet