使用 puppeteer 创建一个自动化导出 PDF 的服务 (2)

创建 PDF:

/** * create pdf with file path return * @param {String} url a web page url to fetch * @param {Object} * @param {Array} cookie A array with cookie Object * @param {Object} pdfOptions options for puppeteer pdf options, cover the default pdf setting */ async function createPdfFile (url, { cookie, pdfOptions = {} }) { const options = Object.assign({}, defaultPdfOptions, pdfOptions) const page = await browser.open(url, { cookie }) // const filename = path.join(__dirname, '../../static/', getUniqueFilename() + '.pdf') const filename = shellescape([tmp.tmpNameSync()]) await page.pdf({ path: filename, ...options }) await page.close() return filename } async function queueCreatePdfFile (list = []) { const result = await queueExecAsyncFunc(createPdfFile, list, { maxLen: MAX_QUEUE_LEN }) return result } async function createPdfFileMergedBuffer (list) { const files = await queueCreatePdfFile(list) return pdfMerge(files) .then((buffer) => { return Promise.all(files.map((file) => { return new Promise((resolve) => { fs.unlink(file, resolve) }) })).then(() => { return buffer }) }) } 环境部署

DockerFile

FROM wenlonghuo/puppeteer-pdf-base:1.0.0 # COPY package.json /app/package.json COPY . /app USER root ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD="TRUE" RUN rm -rf ./node_modules/ && rm -rf ./example/node_modules/ \ && npm install --production && npm cache clean --force USER pptruser # Default to port 80 for node, and 5858 or 9229 for debug ARG PORT=19898 ENV PORT $PORT EXPOSE $PORT 5858 9229 CMD ["node", "app/index.js"]

使用已经完成的 docker 进行部署的方法是:

docker run -i -t -p 19898:19898 --restart=always --privileged=true wenlonghuo/puppeteer-pdf

然后服务调用接口即可。如果没有其他服务,也可以前端调用,效果会差很多,比如使用 axios 实现调用接口并下载:

axios.post('/pdf/create/files', { list: multi.list.split(',').map(item => ({ url: item })), cookie: multi.cookie, pdfOptions: multi.pdfOptions }, { responseType: 'arraybuffer' }).then(res => { createDownload(res.data) }) function createDownload (text, filename = '导出') { /* eslint-disable no-undef */ const blob = new Blob([text], { type: 'application/pdf' }) const elink = document.createElement('a') elink.download = filename + '.pdf' elink.style.display = 'none' elink.href = URL.createObjectURL(blob) document.body.appendChild(elink) elink.click() URL.revokeObjectURL(elink.href) // 释放URL 对象 document.body.removeChild(elink) }

这种方式的主要问题在于下载完成文件后才会弹出窗口,会让人感觉很慢,服务中应该使用 stream 方式进行处理

总结

虽然服务搭建好了,但由于公司的服务器没有 root 权限,无法搭建 docker 环境,最后还是白折腾一场,只能搭在自己的 vps 上进行当作小实验了。

服务存在的问题:

无流式实现,感觉等待时间有点久

多页面导出页脚的统一设置需要提供统一函数

部分页面导出后会将文字切割分成两页,是 puppeteer 的问题

服务稳定性还有待提高

附:
demo 地址:
仓库地址:https://github.com/wenlonghuo/puppeteer-pdf

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpddgg.html