UNPKG

pdf2html1

Version:

PDF to HTML or Text conversion using Apache Tika. Also generate PDF thumbnail using Apache PDFBox.

136 lines (111 loc) 4.64 kB
const debug = require('debug')('pdf2html'); const cheerio = require('cheerio'); const URI = require('urijs'); const fse = require('fs-extra'); const defaults = require('lodash.defaults'); const gm = require('gm').subClass({ imageMagick: true }); const { spawn } = require('child_process'); const constants = require('./constants'); const executeCommand = async (command, args, options = {}) => { const child = spawn(command, args, { ...options }); return new Promise((resolve, reject) => { debug(`Executing command: ${command} ${args.join(' ')} with options: ${JSON.stringify(options)}`); let stdout = ''; // let stderr = ''; child.stdout.on('data', (data) => { stdout += data.toString(); }); // child.stderr.on('data', function(data) { // stderr += data.toString(); // }); child.on('close', (code, signal) => { if (code !== 0) { reject(new Error(`${command} ${args.join(' ')} failed with exit code ${code} with signal ${signal}. Please check your console.`)); return; } // if (stderr && stderr.length > 0) { // reject(new Error(stderr)); // return; // } resolve(stdout); }); }); }; const resizeImage = (sourceFilepath, targetFilepath, options) => new Promise((resolve, reject) => { gm(sourceFilepath) .resize(options.width, options.height, '!') // use the '!' flag to ignore aspect ratio .write(targetFilepath, (err) => { if (err) { reject(err); return; } resolve(); }); }); const runPDFBox = async (filepath, _options) => { const options = defaults(_options || {}, { page: 1, imageType: 'png', width: 160, height: 226 }); const uri = new URI(filepath); const copyFilePath = constants.DIRECTORY.PDF + uri.filename(); await fse.copy(filepath, copyFilePath); const maxBuffer = options.maxBuffer || 1024 * 2000; const command = 'java'; const commandArgs = ['-jar', `${constants.DIRECTORY.VENDOR + constants.VENDOR_PDF_BOX_JAR}`, 'PDFToImage', '-imageType', options.imageType, '-startPage', options.page, '-endPage', options.page, copyFilePath]; await executeCommand(command, commandArgs, { maxBuffer }); uri.suffix(options.imageType); const pdfBoxImageFilePath = constants.DIRECTORY.PDF + uri.filename().replace(new RegExp(`.${uri.suffix()}$`), `${options.page}.${uri.suffix()}`); const imageFilePath = constants.DIRECTORY.IMAGE + uri.filename(); // Resize image try { await resizeImage(pdfBoxImageFilePath, imageFilePath, options); } catch (err) { await fse.copy(pdfBoxImageFilePath, imageFilePath); } finally { // delete temp pdf file copied await fse.remove(copyFilePath); // delete temp image file created by PdfBox await fse.remove(pdfBoxImageFilePath); } return imageFilePath; }; const runTika = async (filepath, _commandOption, options) => { const maxBuffer = (options && options.maxBuffer) || 1024 * 2000; const commandOption = _commandOption || 'html'; const command = 'java'; const commandArgs = ['-jar', `${constants.DIRECTORY.VENDOR + constants.VENDOR_TIKA_JAR}`, `--${commandOption}`, filepath]; return executeCommand(command, commandArgs, { maxBuffer }); }; const html = async (filepath, options) => { debug('Converts PDF to HTML'); return runTika(filepath, 'html', options); }; const pages = async (filepath, _options) => { const options = defaults(_options || {}, { text: false }); debug('Converts PDF to HTML pages'); const result = await html(filepath, options); const $ = cheerio.load(result); const htmlPages = []; const $pages = $('.page'); $pages.each((index) => { const $page = $pages.eq(index); htmlPages.push(options.text ? $page.text().trim() : $page.html()); }); return htmlPages; }; const text = async (filepath, options) => { debug('Converts PDF to Text'); return runTika(filepath, 'text', options); }; const meta = async (filepath, options) => { debug('Extracts meta information from PDF'); return JSON.parse(await runTika(filepath, 'json', options)); }; const thumbnail = async (filepath, options) => { debug('Generate thumbnail image for PDF'); return runPDFBox(filepath, options); }; exports.html = html; exports.pages = pages; exports.text = text; exports.meta = meta; exports.thumbnail = thumbnail;