feat: add page image caching to improve PDF navigation performance
This commit is contained in:
@@ -15,7 +15,7 @@ class PdfHandler {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.storageDir = process.env.PDF_STORAGE_DIR || path.join(process.cwd(), 'data', 'pdfs');
|
this.storageDir = process.env.PDF_STORAGE_DIR || path.join(process.cwd(), 'data', 'pdfs');
|
||||||
this.sessionFile = path.join(this.storageDir, 'sessions.json');
|
this.sessionFile = path.join(this.storageDir, 'sessions.json');
|
||||||
this.sessions = new Map(); // messageId -> { pdfPath, totalPages, ownerId, createdAt, downloadUrl, isPublic }
|
this.sessions = new Map(); // messageId -> { pdfPath, totalPages, ownerId, createdAt, downloadUrl, isPublic, imagePaths }
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.min.js');
|
pdfjsLib.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.min.js');
|
||||||
this.ensureStorageDir();
|
this.ensureStorageDir();
|
||||||
this.loadSessions();
|
this.loadSessions();
|
||||||
@@ -60,7 +60,9 @@ class PdfHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageBuffer = await this.renderPage(pdf, 1);
|
const imagePaths = await this.renderAllPages(pdf, totalPages);
|
||||||
|
|
||||||
|
const pageBuffer = fs.readFileSync(imagePaths[0]);
|
||||||
const title = this.getPdfTitle(sourceUrl);
|
const title = this.getPdfTitle(sourceUrl);
|
||||||
const messageOptions = this.buildMessageOptions(pageBuffer, 1, totalPages, interaction.user.id, sourceUrl, title);
|
const messageOptions = this.buildMessageOptions(pageBuffer, 1, totalPages, interaction.user.id, sourceUrl, title);
|
||||||
|
|
||||||
@@ -78,7 +80,8 @@ class PdfHandler {
|
|||||||
ownerId: interaction.user.id,
|
ownerId: interaction.user.id,
|
||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
downloadUrl: sourceUrl,
|
downloadUrl: sourceUrl,
|
||||||
isPublic
|
isPublic,
|
||||||
|
imagePaths
|
||||||
});
|
});
|
||||||
this.saveSessions();
|
this.saveSessions();
|
||||||
|
|
||||||
@@ -123,8 +126,18 @@ class PdfHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
let pageBuffer;
|
||||||
|
if (session.imagePaths?.[clampedPage - 1] && fs.existsSync(session.imagePaths[clampedPage - 1])) {
|
||||||
|
pageBuffer = fs.readFileSync(session.imagePaths[clampedPage - 1]);
|
||||||
|
} else {
|
||||||
const { pdf } = await this.loadPdf(session.pdfPath);
|
const { pdf } = await this.loadPdf(session.pdfPath);
|
||||||
const pageBuffer = await this.renderPage(pdf, clampedPage);
|
const buffer = await this.renderPage(pdf, clampedPage);
|
||||||
|
const filePath = this.writeImageFile(buffer, clampedPage);
|
||||||
|
session.imagePaths = session.imagePaths || [];
|
||||||
|
session.imagePaths[clampedPage - 1] = filePath;
|
||||||
|
this.saveSessions();
|
||||||
|
pageBuffer = buffer;
|
||||||
|
}
|
||||||
const title = this.getPdfTitle(session.downloadUrl);
|
const title = this.getPdfTitle(session.downloadUrl);
|
||||||
const messageOptions = this.buildMessageOptions(pageBuffer, clampedPage, totalPages, ownerId, session.downloadUrl, title);
|
const messageOptions = this.buildMessageOptions(pageBuffer, clampedPage, totalPages, ownerId, session.downloadUrl, title);
|
||||||
|
|
||||||
@@ -175,6 +188,29 @@ class PdfHandler {
|
|||||||
return sharp(buffer).png({ quality: 90 }).toBuffer();
|
return sharp(buffer).png({ quality: 90 }).toBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rend toutes les pages et retourne la liste des chemins de fichiers
|
||||||
|
*/
|
||||||
|
async renderAllPages(pdf, totalPages) {
|
||||||
|
const paths = [];
|
||||||
|
for (let i = 1; i <= totalPages; i++) {
|
||||||
|
const buffer = await this.renderPage(pdf, i);
|
||||||
|
const filePath = this.writeImageFile(buffer, i);
|
||||||
|
paths.push(filePath);
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Écrit une image en cache et retourne le chemin
|
||||||
|
*/
|
||||||
|
writeImageFile(buffer, pageIndex) {
|
||||||
|
const fileName = `page-${pageIndex}-${Date.now()}-${Math.random().toString(36).slice(2)}.png`;
|
||||||
|
const targetPath = path.join(this.storageDir, fileName);
|
||||||
|
fs.writeFileSync(targetPath, buffer);
|
||||||
|
return targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construit le message Discord avec image + boutons
|
* Construit le message Discord avec image + boutons
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user