背景:
在实际工作中往往只需要预览pdf,可以使用pdfjs-dist这个库来实现预览、解析的功能。但是我遇到过基于原始pdf重新合成新的pdf的功能,在元素pdf上面拖拽一些控件元素,类似checkbox,并且在上面打勾,打勾完成以后需要重新合成一个新的pdf。众所周知,pdf上面只能预览无法编辑。以下只展示核心代码:
1、根据A4纸的大小,等比计算pdf每页的宽高。并使用html2canvas截长图并分页,最后生成新的pdf
async function convertToPDF() {
const element = scrollContainer.value as HTMLElement
const A4_WIDTH = 592.28
const A4_HEIGHT = 841.89
const canvas = await html2canvas(element, {
scale: window.devicePixelRatio || 3,
width: element.offsetWidth,
height: element.offsetHeight,
useCORS: true
})
const canvasWidth = canvas.width
const canvasHeight = canvas.height
// html页面实际高度
let htmlHeight = canvasHeight
// 页面偏移量
let position = 0
// 根据A4纸的宽高等比计算pdf页面对应的高度
const pageHeight = (canvasWidth * A4_HEIGHT) / A4_WIDTH
// html页面生成的canvas在pdf中图片的宽高
const imgWidth = A4_WIDTH
const imgHeight = (A4_WIDTH * canvasHeight) / canvasWidth
const imageData = canvas.toDataURL("image/png", 1.0)
const pdf = new jsPDF("p", "pt", "a4")
// html页面的实际高度小于生成pdf的页面高度时,即内容未超过pdf一页显示的范围,无需分页
if (htmlHeight <= pageHeight) {
pdf.addImage(imageData, "PNG", 0, 0, imgWidth, imgHeight)
} else {
// 内容超过一页时,需要分页
while (htmlHeight > 0) {
pdf.addImage(imageData, "PNG", 0, position, imgWidth, imgHeight)
// 更新高度与偏移量
htmlHeight -= pageHeight
position -= A4_HEIGHT
if (htmlHeight > 0) {
// 在PDF文档中添加新页面
pdf.addPage()
}
}
}
return pdf.output("blob")
}
2、生成blob流以后,使用axios上传到服务器上,具体逻辑根据业务调整,以下只展示粗略代码:
async function uploadFile(blob) {
const randomKey = generateRandomKey()
let params = new FormData()
params.append("file", blob, `${randomKey}`)
try {
let res = await axios.post(`https://obs.${suffix}/api/dc/storage/standard/upload`, params)
if (!res.data.isError) {
return res.data.data.ossUrl
}
} catch (err) {
Toast("上传失败,请稍后再试!")
}
}