Я хочу преобразовать большой список файлов 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();
});