Calendario: il PDF e' un file vero, generato dal server

"Scarica in PDF" non apre piu' la stampa del browser: e' un link a
/calendario/<id>.pdf che restituisce un documento disegnato dal dato con PDFKit,
con Content-Disposition attachment. Serve perche' il calendario si gira su
WhatsApp, ed e' cosi' che questo centro parla coi clienti: chi lo riceve non ha
il sito aperto davanti.

Niente browser headless: Chromium in un container da 2 vCPU costa centinaia di
megabyte e un processo per richiesta, per una griglia di sette colonne.

Le linee della griglia si tracciano in una passata a parte, dopo i riempimenti:
disegnandole riga per riga, il riempimento della riga seguente copriva quella
appena fatta e due lezioni uguali in fasce consecutive si leggevano come un
blocco unico lungo il doppio.

Quattro test: intestazione %PDF- e coda %%EOF (un documento non chiuso arriva
monco e il browser mostra una pagina bianca invece di un errore), una pagina
sola, nomi di file distinti. Un id sconosciuto e' 404, non un PDF vuoto.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 16:14:02 +02:00
parent 01f49ab6d2
commit 5be0fa787c
6 changed files with 416 additions and 11 deletions
+2
View File
@@ -28,6 +28,7 @@
"bcryptjs": "^3.0.3",
"better-sqlite3": "^12.11.1",
"nodemailer": "^9.0.3",
"pdfkit": "^0.19.1",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"recharts": "^3.10.1",
@@ -38,6 +39,7 @@
"@types/bcryptjs": "^2.4.6",
"@types/better-sqlite3": "^7.6.13",
"@types/nodemailer": "^8.0.1",
"@types/pdfkit": "^0.17.6",
"@types/sanitize-html": "^2.16.1",
"marked": "^18.0.7",
"typescript": "^6.0.3",