I want to convert a large list of PDF files to JPEG and compress the images files on the server before sending the archive file for the client.
I use:
- PDFKit to generate my PDF file
- ImageMagic to convert each PDF file to JPEG with the command
convert -density 300 file.pdf -trim -quality 100 file.jpeg archiverfor zipping image files
Problems:
- the
convertcommand is too slow and I have a timeout in the client side if I want to convert a large list of PDF files or a PDF file with many pages. - my archive don't stream directly in the client side
Questions:
- It is possible to generate a JPEG file with PDFKit?
- What I need to do to stream directly the archive to my response?
My code:
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();
});