(async function () {
console.clear();
console.log("======================================");
console.log(" PDF.JS - RENDER TUNG TRANG");
console.log("======================================");
// ==========================================================
// 1. KIỂM TRA PDF.JS
// ==========================================================
const app = window.PDFViewerApplication;
if (!app) {
console.error(
"❌ Không tìm thấy PDFViewerApplication."
);
return;
}
if (!app.pdfDocument) {
console.error(
"❌ PDF.js chưa tải xong tài liệu."
);
return;
}
const pdfDocument = app.pdfDocument;
const totalPages =
pdfDocument.numPages;
console.log(
`📚 Tổng số trang: ${totalPages}`
);
// ==========================================================
// 2. LOAD jsPDF
// ==========================================================
function loadJsPDF() {
return new Promise((resolve, reject) => {
if (
window.jspdf &&
window.jspdf.jsPDF
) {
resolve();
return;
}
const script =
document.createElement("script");
script.src =
"https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js";
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
await loadJsPDF();
const { jsPDF } =
window.jspdf;
console.log("✅ jsPDF OK");
// ==========================================================
// 3. HÀM DELAY
// ==========================================================
function sleep(ms) {
return new Promise(
resolve => setTimeout(resolve, ms)
);
}
// ==========================================================
// 4. RENDER MỘT TRANG
// ==========================================================
async function renderPage(pageNumber) {
console.log(
`⏳ Đang render trang ${pageNumber}/${totalPages}...`
);
const page =
await pdfDocument.getPage(
pageNumber
);
// Scale 1.5 cho chất lượng tương đối tốt
const scale = 1.5;
const viewport =
page.getViewport({
scale: scale
});
const canvas =
document.createElement(
"canvas"
);
const context =
canvas.getContext("2d", {
alpha: false
});
canvas.width =
Math.floor(
viewport.width
);
canvas.height =
Math.floor(
viewport.height
);
const renderTask =
page.render({
canvasContext: context,
viewport: viewport
});
await renderTask.promise;
const image =
canvas.toDataURL(
"image/jpeg",
0.95
);
// Giải phóng
canvas.width = 1;
canvas.height = 1;
return {
image: image,
width: viewport.width,
height: viewport.height
};
}
// ==========================================================
// 5. TẠO PDF
// ==========================================================
let pdf = null;
for (
let i = 1;
i <= totalPages;
i++
) {
try {
const pageData =
await renderPage(i);
const w =
pageData.width;
const h =
pageData.height;
const landscape =
w > h;
// A4
const pageWidth =
landscape
? 297
: 210;
const pageHeight =
landscape
? 210
: 297;
// Giữ nguyên tỷ lệ
const ratio =
Math.min(
pageWidth / w,
pageHeight / h
);
const imageWidth =
w * ratio;
const imageHeight =
h * ratio;
const x =
(pageWidth -
imageWidth) / 2;
const y =
(pageHeight -
imageHeight) / 2;
// Trang đầu
if (!pdf) {
pdf =
new jsPDF({
orientation:
landscape
? "landscape"
: "portrait",
unit: "mm",
format: [
pageWidth,
pageHeight
],
compress: true
});
} else {
pdf.addPage(
[
pageWidth,
pageHeight
],
landscape
? "landscape"
: "portrait"
);
}
pdf.addImage(
pageData.image,
"JPEG",
x,
y,
imageWidth,
imageHeight,
undefined,
"FAST"
);
console.log(
`✅ Trang ${i}/${totalPages} đã thêm vào PDF`
);
await sleep(100);
} catch (error) {
console.error(
`❌ Lỗi trang ${i}:`,
error
);
}
}
// ==========================================================
// 6. LƯU FILE
// ==========================================================
if (!pdf) {
console.error(
"❌ Không tạo được PDF."
);
return;
}
pdf.save(
"tai-lieu-hoan-chinh.pdf"
);
console.log("");
console.log("======================================");
console.log("🎉 HOÀN TẤT");
console.log(
`📄 Đã xử lý ${totalPages} trang`
);
console.log(
"📁 tai-lieu-hoan-chinh.pdf"
);
console.log("======================================");
})();