const { PATH_FILES } = require('../config') const logger = require('../log/index') const puppeteer = require('puppeteer'); const fs = require('fs') const path = require('path') // 生成 async function initBrowser () { logger.log.debug('启动', new Date().toLocaleString()) return await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); } let browser = null function checkCache (fPath) { try { const fStat = fs.statSync(fPath) if (fStat) { const isFile = fStat.isFile() if (isFile) { return fPath } } return false } catch (err) { return false } } function wait(ms) { return new Promise((resolve, reject) => { setTimeout(() => { console.log("Done waiting"); resolve(ms) }, ms) }) } function asyncCheck(delay, step, delayFn) { return new Promise((resolve, reject) => { let attempts = 0; const maxAttempts = Math.ceil(delay / step); // 计算最大尝试次数 const check = () => { delayFn().then(result => { if (result) { resolve({ result: true, type: 'check' }); } else { attempts++; if (attempts > maxAttempts) { resolve({ result: false, type: 'max' }); } else { // 如果还没有达到最大尝试次数,继续查询 setTimeout(check, step); } } }).catch(error => { // 如果delayFn抛出错误,拒绝Promise logger.log.debug('检查页面状态失败', error) setTimeout(() => { resolve({ result: false, type: 'max-error' }); }, delay) }); }; // 启动定时查询 check(); }); } async function createPDFOfURL (url, config = {}) { if (!browser) { browser = await initBrowser() } config = Object.assign( { filename: '', dir: '', nocache: false, width: '950px', height: '1360px', margin: { top: 0, bottom: 0 }, step: 200, check: true }, config) // 文件路径 const outPath = path.join(PATH_FILES, config.dir) if (!fs.existsSync(outPath)) { fs.mkdirSync(outPath); } const outConfig = Object.assign({path: `${config.filename}.pdf`, width: config.width, height: config.height,printBackground: true }, config) outConfig.path = path.join(outPath, outConfig.path) // 检查缓存 if (!config.nocache) { const result = checkCache(outConfig.path) if (result) { logger.log.debug('命中缓存文件') return result } } const page = await browser.newPage(); try { await page.setDefaultNavigationTimeout(0) await page.goto(url, {waitUntil: 'networkidle2'}); logger.log.debug('等待生成', new Date().toLocaleString()) if (config.check) { await asyncCheck(config.delay, config.step, async () => { const result = await page.evaluate(() => { return window.__PDF_LOADED__ || false }) logger.log.debug('页面 __PDF_LOADED__ 状态检查', result) return result }) } else { await wait(config.delay || 1000) } await page.pdf(outConfig); await page.close(); logger.log.debug('当前时间', new Date().toLocaleString()) return outConfig.path } catch (e) { logger.log.debug(e) await page.close(); } } module.exports = createPDFOfURL