12 aprile 2020 19:35
Le dimensioni di una pagina HTML stampata in PDF e altre amenità in Blazor
Durante un mini-progetto personale (vedi sotto) nel quale dovevo preparare un PDF avendo come fonte una pagina HTML, mi è sorto l’interrogativo del titolo, ovvero quale è la dimensione massima di un’immagine (o in generale di un element come un DIV che ha una width height in pixel) per un A4 stampato dal browser?
Non trovando la risposta in rete, mi sono fatto 2 png larghi a sufficienza (li ho fatti 3840x2160, ovvero 4k, se vi serve è qui), sbattuti in una pagina html plain (no bootstrap, no wrapper, no margin nel css) e salvati in PDF da Chrome con i settaggi di default.
La risposta per un A4 verticale è 1058 pixel in larghezza e 1559 in verticale (pixel più pixel meno), come potete sperimentare stampando questa pagina. Curiosamente, switchando in layout verticale le due dimensioni non si scambiano ma differiscono di qualche pixel.
Saputo quindi che la dimensione è circa 1050 pixel, ho provato a impaginare una griglia di thumbnails da 200px cadauno con ovviamente 5 colonne, convinto che se la matematica non è un’opinione 200 x 5 = 1000 e avrei potuto mettere anche 10px di padding tra le foto.
Con mia sorpresa l’effetto è stato tipo questo (provate voi stessi a stampare questa pagina):
Ho provato quindi a schiaffare una foto larga 800px e mi occupava tutta la larghezza. Se però provavo con il righello vicino la cosa funzionava…
Morale: in assenza di un elemento che “tiene allargata” la pagina (come un div container o appunto un’immagine di grande dimensioni), il print preview assume che la pagina abbia una larghezza di circa 640px come si evince dalle nostre foto di 200px in cui ce ne stanno solo 3 più un po’ di spazio.
Siamo curiosi, di che mini-progetto si tratta?
Il target del mini-progetto, chiamato RizTravels, era di creare un unico enorme PDF che contenesse tutti i diari e tutte le photogalleries dei miei viaggi (visto che mia mamma non ha internet, per farle passare il tempo in questa interminabile quarantena, ho pensato di stamparle un mega-tomo o di fornirla di un tablet con su SOLO Adobe Acrobat e un’unica icona!).
Inizialmente dovevo risolvere il problema di come fare a reperire i contenuti dei diari, visto che le pagine del sito non sono in un database o in un CMS (ovviamente il calzolaio ha le scarpe bucate, ecc.). Fortunatamente la maggior parte dei diari aveva un template molto simile e quindi mi sono scritto un “grabber” che mi leggesse la parte centrale della pagina e me le salvasse su un database sql.
Dovevo poi ripulirle di immagini e di link, in quanto volevo un contenuto text-only (all’inizio pensavo più a un .epub/mobi per qualche e-reader).
Per i link è stata sufficiente questa RegEx
Regex.Replace(html, @"<a\b[^>]+>([^<]*(?:(?!</a)<[^<]*)*)</a>", "$1");
mentre per le immagini ho usato un package chiamato HtmlAgilityPack e con poche righe ho risolto il problema
var doc = new HtmlDocument();
doc.LoadHtml(htmlContent);
if (doc.DocumentNode.InnerHtml.Contains("<img"))
{
foreach (var eachNode in doc.DocumentNode.SelectNodes("//img"))
{
eachNode.Remove();
}
}
doc.DocumentNode.OuterHtml;
Per quanto riguarda le PhotoGalleries la cosa è stata molto più semplice, anche perché durante l’ultima riorganizzazione avevo implementato un meccanismo di main albums + sub galleries e quello che ho dovuto fare è stato solo di agganciare viaggi e album con una Foreign Key che mi mancava.
Restava solo il dubbio di quale tecnologia usare per generare il mega-html ciclando tra viaggi, pagine, albums e foto.
Dubbio durato pochi secondi in quanto ormai “c’è solo #Blazor”!!
E quindi: File New Solution, Progetto Model con scaffolding delle Entities e DbContext da Sql, Progetto Service con un paio di servizi/biz che forniscono i dati (in asincrono ovviamente, ma qui ho ancora qualche dubbio/difficoltà), progetto UI in Blazor Server Side che a botte di componenti rende il codice anche “bello da vedere”. Figata!
Per la pagina principale ho usato il code-behind, mentre per i mini componenti da riutilizzare se il codice era di poche righe ho lasciato tutto in un file. Il bello di poter mischiare le cose è uno dei tanti punti positivi di Blazor.
Tip da ricordare, quando si vuole renderizzare del RawHtml (es. anche solo una stringa che contiene “ü”), di castare il nostro contenuto con il tipo MarkupString altrimenti l’html viene “encodato”.
Ci ho messo di più a fare gli abbellimenti per le copertine, l’indice, ecc. che non a realizzare il grosso del lavoro, segno che Blazor è una Raz(z)o..r 😊
Il PDF è venuto di 563 pagine…altro che Guerra & Pace! Spero sia un regalo gradito.
PS e così due giorni su tre del week end pasquale da recluso sono passati…