Vue使用pdf-lib实现为文件流添加水印并预览

之前也写过两篇预览pdf的,但是没有加水印,这是链接:Vue使用vue-pdf实现PDF文件预览,使用pdfobject预览pdf。这次项目中又要预览pdf了,要求还要加水印,做的时候又发现了一种预览pdf的方式,这种方式我觉的更好一些,并且还有个要求就是添加水印,当然水印后端也是可以加的,但是后端说了一堆...反正就是要让前端做,在我看来就是借口、不想做,最近也不忙,那我就给他搞出来好了。下面来介绍一下 

首先预览pdf就很简单了,我们只需要通过window.URL.createObjectURL(new Blob(file))转为一个路径fileSrc后,再通过window.open(fileSrc)就可以了,window.open方法第二个参数默认就是打开一个新页签,这样就可以直接预览了,很方便!就是下面这样子:

Vue使用pdf-lib实现为文件流添加水印并预览_第1张图片

并且右上角自动给我们提供了下载、打印等功能。 

但是要加上水印的话,可能会稍微复杂一点点,我也百度找了好多,发现好多都是在项目里直接预览的,也就是在当前页面或者一个div有个容器用来专门预览pdf的,然后水印的话也是appendChild到容器div中进行的。这不是我想要的,并且也跟我现在预览的方式不一样,所以我的思路就是如何给文件的那个二进制blob流上加上水印,这样预览的时候也是用这个文件流,以后不想预览了、直接下载也要水印也是很方便的。找来找去找到了pdf-lib库,然后就去https://www.npmjs.com/package/pdf-lib这里去看了下使用示例,看了两个例子,发现好像这个很合适哦,终于一波操作拿下了,这就是我想要的。

我这里添加水印共三种方式,第一种就是可以直接传入文本,将文本添加进去作为水印 ;第二种是将图片的ArrayBuffer传递进去,将图片作为水印;因为第一种方式直接传文本只能传英文,我传入汉字就报错了,npm官网好像也有写,这是不可避免的,所以才有了第三种方式,就是也是传入文本,不过我们通过canvas画出来,然后通过toDataURL转为base64路径,然后再通过XHR去加载该图片拿到图片的Blob,再调用Blob的arrayBuffer方法拿到buffer传递进去作为水印,其实第三种和第二种都是图片的形式,第三种会更灵活一些。下面上代码

1. 安装 

npm i pdf-lib

2. 引入 

//我的需求里只用到这么多就够了,其他的按需引入
import { degrees, PDFDocument, rgb, StandardFonts } from 'pdf-lib';

3. 添加水印使用 

3.1 添加文本水印

import { degrees, PDFDocument, rgb, StandardFonts } from 'pdf-lib';
 
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...
 
// Load a PDFDocument from the existing PDF bytes
const pdfDoc = await PDFDocument.load(existingPdfBytes)
 
// Embed the Helvetica font
const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica)
 
// Get the first page of the document
const pages = pdfDoc.getPages()
const firstPage = pages[0]
 
// Get the width and height of the first page
const { width, height } = firstPage.getSize()
 
// Draw a string of text diagonally across the first page
firstPage.drawText('This text was added with JavaScript!', {
  x: 5,
  y: height / 2 + 300,
  size: 50,
  font: helveticaFont,
  color: rgb(0.95, 0.1, 0.1),
  rotate: degrees(-45),
})
 
 
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()
 
// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an