Конвертируйте PDF в JPEG, архивируйте и передавайте результаты с Node.js, ImageMagick и PDFKit. - PullRequest
0 голосов
/ 21 июня 2019

Я хочу преобразовать большой список файлов PDF в JPEG и сжать файлы изображений на сервере перед отправкой файла архива для клиента.

Я использую:

  • PDFKit для создания моего файла PDF
  • ImageMagic для преобразования каждого файла PDF в JPEG с помощью команды convert -density 300 file.pdf -trim -quality 100 file.jpeg
  • archiver для архивирования файлов изображений

Проблемы:

  • команда convert слишком медленная, и у меня есть тайм-аут на стороне клиента, если я хочу преобразовать большой список файлов PDF или файл PDF с большим количеством страниц.
  • мой архив не передается напрямую на стороне клиента

Вопросы:

  • Можно ли создать файл JPEG с помощью PDFKit?
  • Что мне нужно сделать для прямой передачи архива в мой ответ?

Мой код:


const archiver = require("archiver");
const { exec } = require("child_process");
const PDFDocument = require("pdfkit");
const fs = require("fs");
const contentDisposition = require("content-dispisition");

async function convertFile(pdfPath, ouputPath) {
  return new Promise((resolve, reject) => {
    exec(
      `convert -density 300 ${pdfPath} -trim -quality 80 ${ouputPath}`,
      error => (error !== null ? reject(error) : resolve("ok"))
    );
  });
}

const cleanUp = () => {
  // used to clean the generation files and directory
};

function createPdf(path, obj, size = [210, 297]) {
  return new Promise(async (resolve, reject) => {
    const doc = new PDFDocument({
      size,
      margin: 0,
      layout: "landscape"
    });

    /** here is a complex code for drawing PDF images and text */

    const stream = fs.createWriteStream(path);
    stream.on("error", reject);
    stream.on("finish", resolve);

    doc.pipe(stream);
    doc.on("error", reject);
  });
}

function getItems(id) {
  return []; // Return a list of object for PDF files
}

// Express router
Router.get("/api/card/:id", async function route(req, res) {
  res.header("Content-Type", `application/zip`);
  res.header("Content-Disposition", contentDisposition(`file.zip`));

  const archiveStream = archiver("zip", { zlib: { level: 9 } });

  archiveStream.pipe(res);

  archiveStream.on("end", cleanUp);
  archiveStream.on("error", err => {});

  let i = 0;
  for (const obj of getItems(req.params.id)) {
    const filename = `myfile-${i++}`;

    // Create my pdf file
    await createPdf(`${filename}.pdf`, obj);

    // Convert PDF to JPEG
    await convertFile(`${filename}.pdf`, `${filename}.jpeg`);

    // Add JPEG file to archive
    archiveStream.append(fs.createReadStream(`${filename}.jpeg`), {
      name: `${filename}.jpeg`
    });
  }

  archiveStream.finalize();
});


...