nodeJS如何将docx转换为pdf
摘要:
本篇文件介绍在NodeJs中如何将Docx转换为PDF,通过使用libreoffice-convert和libreoffice进行转换。Docx文件在前端不太好分页,在前端需要控制用户的进度时使用PDF,已达到监听用户阅读进度及控制用户阅读速度的问题。
前言:最近做项目时,需要用户端展示
docx
文档,并监听用户当前阅读到第几页,控制用户在每页必须停留指定秒数,在使用了docx-to-pdf
、docx-preview
、mammoth
等库后,发现效果都不太理想,特别是分页方面。
上面提到的几个库的问题:
docx-preview
:分页有问题,需要docx
文档中有分页符才行。mammoth
:复杂样式丢失,这是此库故意而为,旨在让开发者使用css控制样式,但因我的需求里的文档文件内容不确定,就不太适用了。(用于导出docx
的内容文字比较好用)docx-to-pdf
:一个整合怪,使用mammoth
和html-pdf
实现,继承了mammoth
的问题,没有复杂样式。
基于以上问题,最终选择了在服务端将docx
转换为pdf
,前端通过pdf.js
进行控制即可。
安装依赖
bash
npm i libreoffice-convert
安装libreoffice
libreoffice-convert
库依赖libreoffice
,需要先下载安装,地址:https://zh-cn.libreoffice.org/download/libreoffice/
编写代码
- 在有
libreoffice
环境变量的情况下,直接调用方法即可
js
libre.convert('test.docx', '.pdf', undefined, (err, done) => {
if (err) {
return console.log('转换失败!', err)
}
fs.writeFileSync('test.pdf', done)
console.log('转换成功!')
})
- 在没有
libreoffice
环境变量的情况下,特别时docker中,需要先安装程序,然后指定程序路径。
js
libre.convertWithOptions('test.docx', '.pdf', undefined, {
// 指定libreoffice程序的路径,这里使用window事例,其他系统同理
sofficeBinaryPaths: ['C:/Program Files/LibreOffice/program/soffice.exe'],
}, (err, done) => {
if (err) {
return console.log('转换失败!', err)
}
fs.writeFileSync('test.pdf', done)
console.log('转换成功!')
})

完整代码实现
对指定目录下的
docx
文件进行转换,并将转换后的文件存放在指定目录。
js
const libre = require('libreoffice-convert')
const path = require('path')
const fs = require('fs')
// 存放docx的目录
const docxDirPath = path.join(__dirname, 'docx')
// 存放pdf的目录
const pdfDirPath = path.join(__dirname, 'pdf')
start()
// 启动
async function start() {
const files = readDocxFile()
// 队列执行,最大并行10个
const results = await executeAsyncFunctionInQueue(ConvertDocToPdf, files, 10)
console.log('转换完成', results)
}
// 获取目录下的所有docx文件
function readDocxFile() {
const files = fs.readdirSync(docxDirPath)
return files.filter((file) => file.endsWith('.docx'))
}
// 转换函数
function ConvertDocToPdf(file, index) {
console.log(`开始转换第${index + 1}个文件: ${file}`)
return new Promise((resolve, reject) => {
const inputPath = path.join(docxDirPath, file)
const outputPath = path.join(pdfDirPath, file.replace('.docx', '.pdf'))
const docData = fs.readFileSync(inputPath)
libre.convert(docData, '.pdf', undefined, (err, done) => {
console.log(`第${index + 1}个文件: ${file}转换${err ? '失败' : '成功'}`)
if (err) {
return reject({
name: file,
error: err
})
}
fs.writeFileSync(outputPath, done)
resolve({
name: file,
error: null
})
})
})
}
/**
* 队列执行函数
* @param {Function} asyncFunction 异步函数
* @param {Array} params 数据数组
* @param {Number} maxConcurrent 最大并行
* @returns
*/
function executeAsyncFunctionInQueue(
asyncFunction,
params,
maxConcurrent = 10
) {
return new Promise((resolve) => {
const total = params.length
const results = []
const executing = new Set()
const executeNext = async () => {
if (params.length === 0) {
return
}
const currentIndex = total - params.length
const param = params.shift()
const promise = asyncFunction(param, currentIndex)
.then((result) => {
results.push(result)
})
.catch((error) => {
results.push(error)
})
.finally(() => {
executing.delete(promise)
if (executing.size || params.length) {
executeNext()
} else {
resolve(results)
}
})
executing.add(promise)
}
while (executing.size < maxConcurrent && params.length > 0) {
executeNext()
}
})
}
评论
0条评论
暂无内容,去看看其他的吧~