Prima parte (leggi la seconda parte, leggi la terza parte)
In questo articolo, suddiviso per motivi di lunghezza in più parti, cercherò di spiegare il sistema tramite il quale sia possibile monitorare l’upload di un file in modo da visualizzare all’utente lo stato di avanzamento dell’operazione.
Questi articoli non sono vogliono essere un semplice how to, quando invece una dettagliata analisi delle problematiche inerenti a questo sistema diventato ormai di sempre più comune utilizzo sui siti web.
La complessità di tutto questo “giochino” è da imputare principalmente al linguaggio server side che utilizzerò in questi articoli: il PHP.
Vediamo subito il perché.
A grandi linee, l’upload di un file dal browser al server funziona semplicemente così: l’utente seleziona il file dal proprio computer e poi invia la form. In quel momento il browser inizia una trasmissione dati con lo script che riceve i dati della form, inviandogli senza soluzione di continuità i byte che compongono il file in fase di trasmissione.
Lato server il PHP dal momento che inizia la ricezione del file, “appoggia” su un file temporaneo i dati che stanno arrivando finché la trasmissione non sarà terminata o cancellata. Nel secondo caso il PHP provvederà a cancellare il file temporaneo e tutto finisce lì. Nel caso di ricezione avvenuta, lo script riprenderà il controllo e sarà in grado di copiare il file temporaneo dove meglio crede (move_uploaded_file(), non dico certo niente di nuovo.)
Non esistono sistema “nativi” da parte del browser per capire quanti byte ha al momento trasmesso. È possibile utilizzare dei trucchetti lato client che prevedono l’utilizzo di un piccolo Flash movie che fa da “gateway” usando Flash stesso per aprire il socket di trasmissione dati verso il server. In tal caso sarà lo stesso Flash a fornire le indicazioni che ci interessano e la gestione è assai più semplice. Tuttavia l’approccio (usato in tantissime soluzioni di alto livello) non è scevro da problemi e in questa sede non ci interessa.
Senza usare Flash, dunque, quello che occorre fare è chiedere al server continuamente a che punto è arrivato leggendo il file temporaneo che sta crescendo man mano che la trasmissione procede.
Questa richiesta verrà fatta dunque via Ajax, chiedendo ad un altro script PHP lo stato di avanzamento del file xxxyyyzzz…
Sembra facile, ma non è.
Il problema nasce dal fatto, come dicevo poco fa, che stiamo usando PHP. Soltanto dalla versione 5.2 in poi è possibile infatti usare un sistema per chiedere al PHP a che punto è con l’upload. Prima, non esisteva modo… impossibile sapere il nome del file temporaneo da un altro processo, né tantomeno dal processo PHP che lo sta generando.
Dalla versione 5.2 è stato introdotto un “hook” che permette alle estensioni PECL del php di intercettare le fasi di upload di un file (no, non si può fare direttamente da PHP). Ovviamente non è che adesso ci mettiamo lì, con il nostro compilatore C a scrivere la nostra fantastica estensione che usa quell’hook. Questo lavoro, fortunatamente, è già stato fatto da qualcuno.
Credo che la maggior parte degli sviluppatori in PHP siano a conoscenza di APC. Il suo mestiere è duplice. In primis è un cosidetto sistema di “opcache”, ovvero permette al PHP di salvarsi i nostri script “precompilati” (passatemi il termine), in modo da velocizzarne le esecuzioni successive (stessa cosa di eAccelerator o xcache, se conoscete già queste alternative). In secundis, mette a disposizione agli script PHP un buffer di memoria ad accesso rapido, per salvare al suo interno delle informazioni magari lette da un sottostitema più lento (dbms, per esempio). È più o meno quello che fa memcache, solo che in questo caso non c’è bisogno di un servizio esterno che giri. APC infatti è un’estensione del PHP e come tale, una volta che questa sia stata compilata e caricata dal PHP, è disponibile da subito.
Fin qui – credo – nessuna grossa novità.
La cosa interessante è che, dalla versione PHP 5.2, APC implementa appunto la gestione di quel famoso “hook” per il monitoraggio dell’upload, offrendo un sistema ai normali script PHP per interrogare l’andamento della creazione del nostro file. Non solo: tramite il servizio di APC sarà così possibile controllare se il nostro file ha terminato il caricamento, se il caricamento è stato annullato dall’utente o da un problema di rete e fare dei semplici calcoli per sapere anche il “rate” di trasmissione in kbyte.
Nella seconda parte dell’articolo vedremo come fare ad implementare un sistema del genere, usando “solo” HTML, PHP e un po’ di sano JavaScript.
Nel frattempo, assicuratevi di avere a disposizione APC (perlomeno) sulla vostra macchina di sviluppo. In Ubuntu è questione di “sudo apt-get install php-apc” e far ripartire Apache. La configurazione, eventualmente, la troverete in
/etc/php5/apache2/conf.d/apc.ini