Terza parte (leggi la prima parte, leggi la seconda parte)
Dopo aver visto come si debba configurare il sistema per far funzionare l’upload progressivo e aver buttato giù una form HTML e un po’ di PHP, vediamo adesso di chiudere il cerchio parlando dell’ultima cosa di cui abbiamo bisogno: un po’ di JavaScript.
Il flusso delle operazioni sarà il seguente:
- l’utente seleziona il file da spedire ed inizia il caricamento verso il server (preme il tasto Submit, per intenderci)
- lato server, il PHP inizia a ricevere il file e APC traccia in tempo reale lo stato di avanzamento (come visto nella seconda parte)
- sul browser, non appena l’utente ha premuto il tasto di submit della form, uno script JavaScript interrogherà ogni X secondi uno script PHP che gli fornirà le informazioni sullo stato di avanzamento (it’s Ajax, baby)
- lo script JavaScript utilizzerà queste informazioni per aggiornare l’interfaccia utente (visualizzazione della percentuale di caricamento effettuato)
- al termine (o all’interruzione) del caricamento il JavaScript eseguirà delle istruzioni
Premetto che negli esempi che seguono userò la sintassi jQuery. Spero comunque siano chiari anche a chi non è un esperto di questa libreria.
Vediamo come potrebbe apparire lo script più semplice possibile (seguite i commenti):
$('#frm-upload').submit(function() {
var apcid = $(this).find('input[name=APC_UPLOAD_PROGRESS]').val();
var $status = $('#uploadStatus');
setTimeout(pollStatus, 2000);
var polls = 0;
function pollStatus() {
$.getJSON("progress.php?apcid=" + apcid, function(data) {
/* Se la prima volta non otteniamo risultati, qualcosa è andato storto */
if (!data && polls == 0) {
$status.html("Errore nel caricamento, il file potrebbe essere troppo grande. Premi 'stop' nel browser e riprova.");
try {
stop();
} catch(e) {
document.execCommand('Stop');
}
}
/* Verifichiamo se l'upload è terminato oppure cancellato */
if (data && (data.cancel_upload || data.done)) {
if (data.cancel_upload) {
/* Upload cancellato */
}
return;
}
if (data) {
/* Aggiorniamo la percentuale di caricamento */
$status.html(data.filename + ": " + data.percent + "% @ ~" + data.rate + "KB/s (" + data.ETA + " min.)");
}
/* Riattiviamo il polling tra 2 secondi */
setTimeout(pollStatus, 2000);
polls++;
});
}
}
Quello che viene fatto non è altro che temporizzare (ogni due secondi) una richiesta al server, chiedendo lo stato di avanzamento del nostro file. Vediamo un po’ di cose interessanti:
- viene agganciato l’evento submit della form; è da quel momento che ha inizio il nostro monitoraggio
- per la visualizzazione dei dati, viene utilizzato un elemento all’interno della pagina con id “status”
- la prima richiesta al server potrebbe fallire (da qui la necessità di contare i “poll”). Ho notato che questo succede quando per esempio il file è troppo grande rispetto alle dimensioni massime concesse per l’upload
- quando qualcosa è andato storto (file troppo grande), allora conviene premere virtualmente il tasto “stop” del browser per chiudere la connessione al server. Ci sono un paio di modi per farlo, uno IE e uno “tutti gli altri” (da qui il try/catch)
- In questo caso trovo più pratica la setTimeout rispetto alla setInterval. In questo modo sono sicuro che in caso di problemi non mi rimanga un timer attivo a massacrarmi il server.
- “cancel_upload” e “done” sono chiavi della struttura dati che vengono valorizzate automaticamente da APC al termine dell’upload (infatti non erano state descritte nella seconda parte di questo articolo)
OK, fin qui tutto bene (citando un gran bel film).
I problemi arrivano quando l’upload termina. Cosa succede infatti – solitamente – quando si è finito un upload? Si effettua un redirect HTTP da qualche altra parte. In questo caso però – e non ho capito neanche troppo bene perché – il redirect sembra funzionare bene soltanto con Firefox. Gli altri browser si “imbambolano” e, finito l’upload, niente accade. Questo non è un grande problema perché alla fine tutte le altre librerie o gli altri sistemi che ho indagato fanno tutti la stessa cosa, sia per girare intorno a questo problema, sia per ottenere un altro effetto molto simpatico.
Quello che solitamente si fa in questo caso è fare in modo che il target della form sia un IFRAME.
Lo pseudocodice è dunque il seguente:
- si crea un iframe vuoto (src=”about: blank”) e gli si dà un name
- si imposta l’attibuto TARGET del tag FORM al name del nostro IFRAME
- si aggancia l’evento LOAD dell’IFRAME. Sarà questo il modo con cui potremo comunicare delle informazioni dallo script di upload al nostro script JavaScript. L’evento load verrà infatti generato non appena l’upload è terminato.
- all’interno del event handler del load dell’iframe potremo accedere al contenuto (ovvero ad eventuali dati fornitici dallo script di upload) con $iframe.contents().text()
- sempre nell’event handler, modificando la location.href potremmo portare il browser sulla pagina di nostra scelta
Intuitivamente si capisce come un altro vantaggio dell’utilizzo dell’iframe è ottenere l’effetto degli upload di file SENZA fare il submit della form; è quello che succede per esempio quando si allegano dei file ad una mail scritta con GMail.
E per adesso è tutto :)
6 Responses to “Upload progressivo in PHP con APC e JavaScript – Parte 3”
[...] Upload progressivo in PHP con APC e JavaScript (parte 3) – puntate precedenti su RSSWeek#70 [...]
Questo articolo è stato segnalato su ZicZac.it….
Appuntamento numero settanta con RSSWeek: prima scrivevo poco, adesso non sto scrivendo proprio niente. Accontentatevi dei link (quasi) settimanali, nell’attesa che mi torni l’ispirazione. Se vuoi ricevere tutto questo in anteprima, insieme ad un sacco…
This comment was originally posted on Matteo Moro
RSS Week #70: video e letture per il weekend…
Appuntamento numero settanta con RSSWeek: prima scrivevo poco, adesso non sto scrivendo proprio niente. Accontentatevi dei link (quasi) settimanali, nell’attesa che mi torni l’ispirazione. Se vuoi ricevere tutto questo in anteprima, insieme ad un sacco…
This comment was originally posted on Matteo Moro
Sono semplicemente patetici i commenti del conduttore sulla “stravaganza estetica” del giudice Mesiano.
Il giudice, al di fuori del tribunale, è libero di fumare quanto vuole, di vestirsi come vuole, di passeggiare come e dove vuole e, soprattutto, di brindare a quello che vuole.
Il resto sono chiacchiere da salotto (comprese le chiacchiere del giornalista in collegamento) tipiche di trasmissioni come Mattino5.
Dovrebbe invece vergognarsi il conduttore che, da giornalista e scrittore quale dovrebbe essere, si ritrova a presentare un programma basato sul… niente.
This comment was originally posted on Matteo Moro
Grazie del link!
This comment was originally posted on Matteo Moro
@Luca:
Grazie a te del post
This comment was originally posted on Matteo Moro
Additional comments powered by BackType