程序员网站建设青岛网站设计微动力
场景:前端下载 pdf 文件的时候,需要加上水印,再反给用户下载
用到的库:pdf-lib
和 @pdf-lib/fontkit
一、引入pdf-lib插件
使用 cdn 引入 pdf-lib 包
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.14.1/pdf-lib.min.js"></script>
使用 cdn 引入自定义字体工具,因pdf-lib添加水印时默认不支持中文,所以必须自定义一个字体来显示中文水印
<script src="https://unpkg.com/@pdf-lib/fontkit/dist/fontkit.umd.js"></script>
引入文件下载工具,pdf添加水印后直接使用该工具下载
<script src="https://unpkg.com/downloadjs@1.4.7"></script>
二、 使用pdf-lib
index.js文件:
可直接粘贴下去测试,需要注意代码中的以下两个路径问题:
1. const url = './201805510.pdf'; 这个路径是你需要放在index.js同个项目中的pdf文件
2. const fonturl = './watermarkfont.ttf'; 这个路径是你需要放在index.js同个项目中的下载好的自定义字体文件路径
有vscode + live-server 条件的话,可通过以下方法运行这个pdf添加水印功能
创建一个project文件夹,将 index.js、pdf文件、自定义字体文件.ttf 放在该文件夹中,用vscode打开project文件夹,使用live-server运行该文件夹就能测试该pdf水印添加功能
<html><head><meta charset="utf-8" /><script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.14.1/pdf-lib.min.js"></script><script src="https://unpkg.com/@pdf-lib/fontkit/dist/fontkit.umd.js"></script><script src="https://unpkg.com/downloadjs@1.4.7"></script>
</head><style>body {width: 100vw;height: 100vh;display: flex;justify-content: center;align-items: center;flex-direction: column;}p {font-family: helvetica;font-size: 24px;text-align: center;margin: 25px;}.small {font-family: helvetica;font-size: 18px;text-align: center;margin: 25px;}button {background-color: #008CBA;border: none;color: white;padding: 15px 32px;text-align: center;font-size: 16px;}
</style><body><p>点击这个按钮通过<code>pdf-lib</code>给原来的pdf文件添加水印</p><button onclick="modify()">Modify PDF</button><p class="small">(点击后自动下载修改完成后的pdf文件)</p>
</body><script>//1. 引入相关对象和方法const { degrees, PDFDocument, rgb, StandardFonts } = PDFLib //引入PDFLib相关方法const fontkit = window.fontkit; //引入自定义字体工具包// pdf浏览async function modify() {/*2. 获取pdf文件的arrarybuffer文件流可请求后台接口返回的base64文件流,然后转成arrayBuffer类型可访问前端项目中的本地文件不能直接访问服务器链接文件,会有跨域问题*/const url = './201805510.pdf';const existingPdfBytes = await fetch(url).then(res => res.arrayBuffer())// 将arraybuffer数据转成pdf文档const pdfDoc = await PDFDocument.load(existingPdfBytes)//3. 自定义字体,如不需要使用自定义字体可以将这一段全部注释掉,也不用下载自定义字体文件和自定义字体工具fontkit//将自己下载好的.ttf文件放置项目中,然后访问文件路径const fonturl = './watermarkfont.ttf';const fontBytes = await fetch(fonturl).then((res) => res.arrayBuffer());// 自定义字体挂载、fontkit为自定义字体注册工具pdfDoc.registerFontkit(fontkit)const customFont = await pdfDoc.embedFont(fontBytes)// 内置字体(不支持中文), 如果水印中不包含中文可直接用内置字体,本次这里没用到内置字体const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica)//4. 添加水印//为每页pdf添加文字水印const pages = pdfDoc.getPages()for (let i = 0; i < pages.length; i++) {const noPage = pages[i]const { width, height } = noPage.getSize()for (let i = 0; i < 10; i++) {for (let j = 0; j < 3; j++) {noPage.drawText('水印', {x: 230 * j,y: (height / 4) * i,size: 16,font: customFont, //这里使用的是自定义字体//使用上面定义好的内置字体 font:helveticaFont color: rgb(0.46, 0.53, 0.6),rotate: degrees(45),opacity: 0.3,})}}}//5. 保存pdf文件的unit64Arrary文件流const pdfBytes = await pdfDoc.save();download(pdfBytes, 'test.pdf', "application/pdf"); //下载带水印的pdf//6. 新标签页预览、打印let blobData = new Blob([pdfBytes], { type: "application/pdf;Base64" });let a = document.createElement("a");a.target = "_blank";a.href = window.URL.createObjectURL(blobData);document.body.appendChild(a);a.click();document.body.removeChild(a);}</script></html>