75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import * as pdfjs from "pdfjs-dist";
|
|
import pdfWorker from "pdfjs-dist/build/pdf.worker.min.mjs?url";
|
|
import { LIMITS, fileTooLargeMessage, tooManyPagesMessage } from "@shared/types";
|
|
|
|
pdfjs.GlobalWorkerOptions.workerSrc = pdfWorker;
|
|
|
|
function canvasToJpeg(canvas: HTMLCanvasElement): Promise<Blob> {
|
|
return new Promise((resolve, reject) => {
|
|
canvas.toBlob(
|
|
(blob) => {
|
|
if (!blob) reject(new Error("تبدیل تصویر ناموفق بود"));
|
|
else resolve(blob);
|
|
},
|
|
"image/jpeg",
|
|
LIMITS.jpegQuality / 100,
|
|
);
|
|
});
|
|
}
|
|
|
|
export async function renderPdfToJpegs(
|
|
file: File,
|
|
onProgress?: (done: number, total: number) => void,
|
|
): Promise<Blob[]> {
|
|
if (file.size > LIMITS.maxFileBytes) {
|
|
throw new Error(fileTooLargeMessage(file.size));
|
|
}
|
|
|
|
const data = new Uint8Array(await file.arrayBuffer());
|
|
let pdf;
|
|
try {
|
|
pdf = await pdfjs.getDocument({ data }).promise;
|
|
} catch (err) {
|
|
const name =
|
|
err && typeof err === "object" && "name" in err
|
|
? String((err as { name: string }).name)
|
|
: "";
|
|
if (name === "PasswordException") {
|
|
throw new Error("این PDF رمزگذاری شده است و قابل تبدیل نیست.");
|
|
}
|
|
if (name === "InvalidPDFException") {
|
|
throw new Error("این فایل یک PDF معتبر نیست.");
|
|
}
|
|
throw err;
|
|
}
|
|
if (pdf.numPages < 1) {
|
|
throw new Error("این PDF صفحهای برای نمایش ندارد.");
|
|
}
|
|
if (pdf.numPages > LIMITS.maxPages) {
|
|
throw new Error(tooManyPagesMessage(pdf.numPages));
|
|
}
|
|
|
|
const pages: Blob[] = [];
|
|
onProgress?.(0, pdf.numPages);
|
|
for (let i = 1; i <= pdf.numPages; i++) {
|
|
const page = await pdf.getPage(i);
|
|
const base = page.getViewport({ scale: 1 });
|
|
const scale = Math.min(LIMITS.maxPageWidth / base.width, 2);
|
|
const viewport = page.getViewport({ scale });
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = Math.floor(viewport.width);
|
|
canvas.height = Math.floor(viewport.height);
|
|
const ctx = canvas.getContext("2d");
|
|
if (!ctx) throw new Error("تبدیل تصویر ناموفق بود");
|
|
const renderTask = page.render({
|
|
canvasContext: ctx,
|
|
canvas,
|
|
viewport,
|
|
} as Parameters<typeof page.render>[0]);
|
|
await renderTask.promise;
|
|
pages.push(await canvasToJpeg(canvas));
|
|
onProgress?.(i, pdf.numPages);
|
|
}
|
|
return pages;
|
|
}
|