瀏覽代碼

Diagnostica step-by-step upload PDF in console

main
Lorenzo Pollutri 2 週之前
父節點
當前提交
19bb7fffbc
共有 1 個檔案被更改,包括 85 行新增21 行删除
  1. +85
    -21
      app/admin/page.tsx

+ 85
- 21
app/admin/page.tsx 查看文件

@@ -172,6 +172,16 @@ async function uploadBlobAsImage(blob: Blob, name: string): Promise<string | nul
const formData = new FormData();
formData.append('file', new File([blob], name, { type: blob.type || 'image/png' }));
const res = await fetch(withBasePath('/api/upload'), { method: 'POST', body: formData });
// Se il server rifiuta (4xx/5xx) propaga il messaggio specifico, così il chiamante
// (pdfToImageItems / handleUploadExtraMedia) vede la causa invece di un null muto.
if (!res.ok) {
let serverMsg = `HTTP ${res.status}`;
try {
const errBody = await res.json();
if (errBody?.error) serverMsg = errBody.error;
} catch { /* response non era JSON */ }
throw new Error(`/api/upload rejected "${name}": ${serverMsg}`);
}
const data = await res.json();
return data.url || null;
}
@@ -216,35 +226,80 @@ async function pdfToImageItems(
file: File,
onProgress: (page: number, total: number) => void
): Promise<MediaItem[]> {
const pdfjs = await import('pdfjs-dist');
// Log step-by-step nella console del browser per poter diagnosticare un fallimento.
// Apri DevTools → Console e filtra per "[pdf]" per vedere ogni passo.
const log = (msg: string, extra?: unknown) => {
if (extra !== undefined) console.info(`[pdf] ${msg}`, extra);
else console.info(`[pdf] ${msg}`);
};
log(`start: file="${file.name}", size=${(file.size / 1024).toFixed(1)} KB, type="${file.type}"`);
let pdfjs;
try {
pdfjs = await import('pdfjs-dist');
log(`pdfjs-dist imported`);
} catch (err) {
throw new Error(`Could not load the PDF library (pdfjs-dist). ${(err as Error).message}`);
}
// Worker file is copied to /public via the postinstall script. Must include the
// basePath so the browser can find it when the app is mounted under /cards.
pdfjs.GlobalWorkerOptions.workerSrc = withBasePath('/pdf.worker.min.mjs');
const workerUrl = withBasePath('/pdf.worker.min.mjs');
pdfjs.GlobalWorkerOptions.workerSrc = workerUrl;
log(`worker set to ${workerUrl}`);
const arrayBuffer = await file.arrayBuffer();
const pdf = await pdfjs.getDocument({ data: arrayBuffer }).promise;
log(`file loaded into memory (${arrayBuffer.byteLength} bytes)`);
let pdf;
try {
pdf = await pdfjs.getDocument({ data: arrayBuffer }).promise;
} catch (err) {
// getDocument fallisce per: worker non raggiungibile (404), PDF cifrato, PDF malformato.
throw new Error(`Could not open the PDF (pdfjs getDocument failed): ${(err as Error).message}. The PDF may be encrypted, corrupted, or the pdf.worker file may not be reachable at ${workerUrl}.`);
}
log(`PDF opened: ${pdf.numPages} pages`);
const baseName = file.name.replace(/\.pdf$/i, '').replace(/[^a-zA-Z0-9-_]/g, '_');
const items: MediaItem[] = [];
for (let i = 1; i <= pdf.numPages; i++) {
log(`page ${i}/${pdf.numPages}: rendering...`);
onProgress(i, pdf.numPages);
const page = await pdf.getPage(i);
const viewport = page.getViewport({ scale: 1.5 });
const canvas = document.createElement('canvas');
canvas.width = viewport.width;
canvas.height = viewport.height;
const ctx = canvas.getContext('2d');
if (!ctx) continue;
await page.render({ canvasContext: ctx, viewport }).promise;
const blob: Blob = await new Promise((resolve, reject) => {
canvas.toBlob(b => b ? resolve(b) : reject(new Error('toBlob failed')), 'image/png');
});
const url = await uploadBlobAsImage(blob, `${baseName}-page${i}.png`);
if (url) items.push({ url });
try {
const page = await pdf.getPage(i);
const viewport = page.getViewport({ scale: 1.5 });
const canvas = document.createElement('canvas');
canvas.width = viewport.width;
canvas.height = viewport.height;
const ctx = canvas.getContext('2d');
if (!ctx) {
log(`page ${i}: skipped — could not get 2D canvas context`);
continue;
}
await page.render({ canvasContext: ctx, viewport }).promise;
log(`page ${i}: rendered (${viewport.width}x${viewport.height})`);
const blob: Blob = await new Promise((resolve, reject) => {
canvas.toBlob(b => b ? resolve(b) : reject(new Error('canvas.toBlob returned null (PNG encoding failed)')), 'image/png');
});
log(`page ${i}: encoded to PNG (${(blob.size / 1024).toFixed(1)} KB)`);
const url = await uploadBlobAsImage(blob, `${baseName}-page${i}.png`);
if (url) {
log(`page ${i}: uploaded → ${url}`);
items.push({ url });
} else {
log(`page ${i}: upload returned no URL (server response had no .url field — check the /api/upload network response)`);
}
} catch (err) {
// Propaga ma con contesto sulla pagina specifica così l'utente vede DOVE.
throw new Error(`Failed on page ${i}: ${(err as Error).message}`);
}
}
log(`finished: ${items.length} pages uploaded successfully`);
return items;
}
@@ -505,9 +560,18 @@ export default function AdminDashboard() {
}
}
} catch (err) {
console.error('Upload failed for', file.name, err);
const reason = (err as Error)?.message || 'unknown error';
showToast(`Failed to process "${file.name}": ${reason}. Check the browser console for details.`, 'error');
// Dump completo nella console (stack incluso) per il debug step-by-step
// visibile in DevTools → Console. L'utente vede invece la causa nel toast.
const e = err as Error;
console.error(`[upload] Failed to process "${file.name}"`);
console.error(`[upload] Message: ${e?.message ?? '(no message)'}`);
console.error(`[upload] Stack:`, e?.stack ?? '(no stack)');
console.error(`[upload] Raw error object:`, err);
const reason = e?.message || 'unknown error';
showToast(
`Failed to process "${file.name}": ${reason}. Open DevTools (F12) → Console and filter by "[pdf]" or "[upload]" to see step-by-step diagnostics.`,
'error',
);
setPdfProgress(null);
}
}


Loading…
取消
儲存