PDF文件分割一些软件开始收费,本着能写代码不下软件的,编程启动!
〇、代码环境
pnpm -v
9.14.2node -v
v22.0.0pdf-lib
^1.17.1
使用Node.js的包管理pnpm工具安装第三方模块pdf-lib
。若没有pnpm 可以额外执行安装:
npm i -g pnpm //已安装pnpm可忽略
pnpm install pdf-lib
一、分割PDF文件
1.0 起始代码
//1处理PDF.js
const fsPro = require('fs/promises');
const { PDFDocument } = require('pdf-lib');
//单页调用
处理PDF('A.pdf', '第1页.pdf', [1]);
处理PDF('A.pdf', '第2页.pdf', [2]);
处理PDF('A.pdf', '第3页.pdf', [3]);
处理PDF('A.pdf', '第1-3页.pdf', [1, 2, 3]);
//循环调用
for (let i = 1; i <= 10; i++) {
处理PDF('A.pdf', `第${i}页.pdf`, [i]);
}
async function 处理PDF(输入路径, 输出路径, 页码列表) {
try {
const 文件内容 = await fsPro.readFile(输入路径);
const 输入PDF = await PDFDocument.load(文件内容);
const 新PDF = await PDFDocument.create();
for (let 页码 of 页码列表) {
if (!Number.isInteger(页码) || 页码 <= 0) {
throw new Error(`无效的页面索引: ${页码}。页面索引必须是正整数。`);
}
const [复制页] = await 新PDF.copyPages(输入PDF, [页码 - 1]);
新PDF.addPage(复制页);
}
const 新文件内容 = await 新PDF.save();
await fsPro.writeFile(输出路径, 新文件内容);
console.log(` ${输出路径} 文件提取成功!`);
} catch (错误) {
if (错误.errno === -4056) {
console.error(`检查这个 ${输入路径} 文件不存在`);
} else {
console.error(`${输出路径} 文件发生错误:`, 错误);
}
}
}
1.1 自定义截取函数
问题2:要生成第4、5、6...99、100页,我该怎么传入参数
答案: [4,5,6,...,99,100]
传参不太方便,需要穿一个完整的数组 自定义一个页码截取函数,可以设置2000页使用slice截取,注意此处页码要从1开始。
// 2截取.js
console.log( 截取(4,100) ) //第4页,到第100页
console.log( 截取(4,10) )
//待完成:输出 从第1页 截取到学号后2位的页码
function 截取(起,终){
let arr = []
for(let i= 0;i<=2000;i++){
arr.push(i)
}
return arr.slice(起,终+1)
}//截取(起,终)
将以上两部分代码截图起来:
现在执行代码语句只用传入起始页和结束页,以下两种写法是等价的。
提取页面('A.pdf', '第1-8页.pdf', [1,2,3,4,5,6,7,8] );
提取页面('A.pdf', '第1-8页.pdf', 截取(1,8) );
1.2 代码执行效果演示
1.3 完整代码
//1处理PDF.js
const fsPro = require('fs/promises');
const { PDFDocument } = require('pdf-lib');
处理PDF('A.pdf', '模块一样卷5.pdf', 截取(3,11) )
处理PDF('A.pdf', '模块二样卷5.pdf', 截取(11,23) )
处理PDF('A.pdf', '模块三样卷5.pdf', 截取(24,29) )
async function 处理PDF(输入路径, 输出路径, 页码列表) {
try {
const 文件内容 = await fsPro.readFile(输入路径);
const 输入PDF = await PDFDocument.load(文件内容);
const 新PDF = await PDFDocument.create();
for (let 页码 of 页码列表) {
if (!Number.isInteger(页码) || 页码 <= 0) {
throw new Error(`无效的页面索引: ${页码}。页面索引必须是正整数。`);
}
const [复制页] = await 新PDF.copyPages(输入PDF, [页码 - 1]);
新PDF.addPage(复制页);
}
const 新文件内容 = await 新PDF.save();
await fsPro.writeFile(输出路径, 新文件内容);
console.log(` ${输出路径} 文件提取成功!`);
} catch (错误) {
if (错误.errno === -4056) {
console.error(`检查这个 ${输入路径} 文件不存在`);
} else {
console.error(`${输出路径} 文件发生错误:`, 错误);
}
}
}
function 截取(起,终){
let arr = []
for(let i= 0;i<=2000;i++){
arr.push(i)
}
return arr.slice(起,终+1)
}//截取(起,终)
二、合并PDF文件
2.0 完整代码
const fsPro = require('fs/promises')
const { PDFDocument } = require('pdf-lib')
//步骤2.1 传入参数格式和调用
const 文件数组 = ['第1页.pdf', '第2页.pdf', '第3页.pdf']
const 输出路径 = '第1-3页.pdf'
合并PDF(文件数组, 输出路径)
async function 合并PDF(文件数组, 输出路径) {
try {
//关键1. 创建一个新的PDF空文档
const PDF空文档 = await PDFDocument.create()
for (const 文件 of 文件数组) {
const 文件内容 = await fsPro.readFile(文件)
const 读取PDF = await PDFDocument.load(文件内容)
const 总页数 = 读取PDF.getPageCount()
for (let 页码 = 0; 页码 < 总页数; 页码++) {
const [复制页] = await PDF空文档.copyPages(读取PDF, [页码])
PDF空文档.addPage(复制页)
}
}
const 新文件内容 = await PDF空文档.save()
await fsPro.writeFile(输出路径, 新文件内容)
console.log(`${输出路径} 文件合并成功!`)
} catch (错误) {
console.error(`合并文件发生错误:`, 错误)
}
}
2.1 传入参数格式和调用
const 文件数组 = ['第1页.pdf', '第2页.pdf', '第3页.pdf']
const 输出路径 = '第1-3页.pdf'
合并PDF(文件数组, 输出路径)
2.2 创建一个新的PDF空文档
const PDF空文档 = await PDFDocument.create()
2.3 遍历文件数组
使用 readFile
读取PDF文件内容
使用 PDFDocument.load()
加载读取到的PDF文件内容
使用getPageCount()
获取加载PDF总页数
for (const 文件 of 文件数组) {
const 文件内容 = await fsPro.readFile(文件)
const 读取PDF = await PDFDocument.load(文件内容)
const 总页数 = 读取PDF.getPageCount()
//...
}
2.4 复制每一页到新的PDF空文档
使用 copyPages(PDF对象,页码数组)
读取PDF页面,
使用 PDFDocument.addPage()
添加复制的页面
for (const 文件 of 文件数组) {
//...
for (let 页码 = 0; 页码 < 总页数; 页码++) {
const [复制页] = await PDF空文档.copyPages(读取PDF, [页码])
PDF空文档.addPage(复制页)
}
}
2.5 保存新的PDF文档
新PDF文档.save()
是 pdf-lib
库提供的方法,用于将当前的PDF文档状态保存为二进制数据。返回的结果是一个Buffer对象,包含PDF文件的二进制数据。
const 新文件内容 = await PDF空文档.save()
await fsPro.writeFile(输出路径, 新文件内容)
三、pnpm常见错误
1、提示:network err...seconds 等
通常是网络问题,确定网络状况良好。可以重复尝试。 下载模块太慢 配置淘宝镜像源
pnpm config set registry https://registry.npmmirror.com/
2、提示:禁止在系统上运行脚本
这里有多种方法都是目的就是授权命令,
2.1使用VScode中的终端
使用管理员权限打开VScode,在任意位置的命令行终端执行:
set-ExecutionPolicy RemoteSigned
即可立即生效。
2.2使用系统自带的终端
Win+R键输入cmd,回车输入 set-ExecutionPolicy RemoteSigned
输入Y确认即可。
解决办法:在电脑中 使用管理员身份运行 Windows PowerShell !
3、写入文件路径错误
发现是有的同学将代码放在了U盘里!神操作啊。经常修改的代码不要放在U盘里修改或者运行, 会极大地减少U盘寿命,并且代码写入的权限容易不稳定!
四、附录
1.pdf-lib库及作者信息(更新于3年前)