前端处理现有的pdf
近期, 业务方希望能有一个工具能够给图片或者pdf加入水印.方便用户的使用.
分析一下需要的功能
- 上传的 png, jpg 图片自动转换成pdf, 并加入水印
- 上传的 pdf, 加入水印
功能上, 主要是对现有的pdf进行加入水印. 也就是修改pdf.
解决方案
awesome-javascript 在里面有常用的PDF处理库.
但是, 仅供参考. 还有一些优秀库, 它里面没有包含.
通过一番搜索和对比有3个库可能满足需求
- jsPDF 生成pdf有许多方便的方法, 但是不支持修改现有的pdf.
- pdfkit 生成pdf, 但是不支持修改现有的pdf.
- pdf-lib 生成pdf有一些方法比较原始,需要自己适配.
支持修改现有的pdf
.
综上, 选择了 pdf-lib
其中找到pdf-lib库, 还是通过在 jsPDF/issues/131 看到下面的
https://github.com/Hopding/pdf-lib is an alternative that can handle merging, splitting pages etc.
I’m using both libraries for different purposes.
pdf-lib
根据pdf-lib上的demo, 进行了实验.
发现还是挺简单的.
但是, 需要提醒几个点
坐标
左下角是原点
pdf旋转
pdf是可以旋转的. 但是一旦旋转之后, 可能水印的位置就不对了.
例如, 旋转90度.如图:
会导致原来的坐标位置就不对了.
需要自己适配一下
下面的我适配的代码, 仅供参考
// 如果传入的是负数, 就认为是距离边界多少
function getDistance(distance, offset) {
if (offset < 0) {
return distance + offset
} else {
return offset
}
}
// 求弧度 角度 * Math.PI/180
function radian(angle){
return angle * Math.PI /180
}
// 这里没有考虑pdf原本是宽要大于高的情况
// 代码应该考虑一些特殊情况, 和不能只适配90 180 270
// 应该可以写成 固定的公式
WatermarkPdf.getStartPoint = function (page, offset) {
let rotation = page.getRotation()
let width = Math.min(page.getHeight(), page.getWidth())
let height = Math.max(page.getHeight(), page.getWidth())
let angle = rotation.angle
let x = 0
let y = 0
let {
offsetX, offsetY } = offset
// 宽高需要根据 angle 进行切换
if (angle == 0) {
x = getDistance(width, offsetX)
y = getDistance(height, offsetY)
}
if (angle === 90) {
x = getDistance(width, 0 - offsetY)
y = getDistance(height, offsetX)
}
if (angle == 270) {
x = getDistance(width, offsetY)
y = getDistance(height, 0 - offsetX)
}
return {
x, y }
}
jpg png
pdf-lib中没有对jpg和png自行适配.
而是需要我们自己进行图片格式的识别.
当用户上传文件后, 我们可以得到一个File
类型的对象.
它继承了 Blob
, 所以可以拿到ArrayBuffer. 也可以获取到文件的类型;
从而进行适配
可以看我的例子:
async handleImage