Fino all'uscita di Flash 8, eseguire e gestire il download e l'upload di un file sul server, tramite Flash, era quasi un'avventura per pochi temerari: alcuni sviluppatori avevano reso disponibili dei componenti, tuttavia spesso c'erano problemi di compatibilità tra i diversi browser. Il download era invece limitato all'uso del comando getURL, tuttavia, in caso di file apribili con il browser (nativamente o tramite plugin, per esempio i file in PDF), era necessario comprimere i file in formato ZIP o comunque in formati che il browser non provasse ad eseguire direttamente.
Con Flash 8 le cose cambiarono notevolmente, grazie all'avvento della classe FileReference che permette la gestione di download e upload di file tramite Flash (anche se per l'upload è necessario appoggiarsi ad un file PHP, .NET o affine presente sul server).
In questo articolo vedremo come usare la classe FileReference (in Actionscript 3) per caricare un file sul server e come usarla per eseguire il download di un file, anche se in formati che verrebbero normalmente aperto dal browser.
Va notato come la classe FileReference non ha subito particolari modifiche alla sintassi nella trasposizione da Actionscript 2 ad Actionscript 3, tuttavia in quest'ultima versione va utilizzata la nuova gestione degli eventi prevista in AS3, inoltre sia per il download che per l'upload viene utilizzata la classe URLRequest.
Upload di un file tramite Flash
Vediamo allora come sia possibile caricare un file sul server dal proprio PC: vedremo come far aprire a Flash la finestra di dialogo per la scelta del file, passeremo le informazioni necessarie per il trasferimento a un file PHP, quindi, grazie ai numerosi eventi messi a disposizione dalla classe FileReference, monitoreremo il trasferimento (progresso e completamento, o eventuali errori).
Per prima cosa impostiamo le variabili relative all'URL del file PHP (o affine) che sposterà fisicamente il file, all'oggetto URLRequest che useremo per inviare il file selezionato dall'utente da Flash a PHP e all'oggetto FileReference che gestirà le diverse operazioni.
Listato 1. Imposta le variabili
// importazione dei package
import flash.net.URLRequest
import flash.net.FileReference
// Imposto il file server-side che uploaderà fisicamente il file
var uploader:String= "uploader.php"
// Creo l'URLRequest che comunicherà con l'uploader
var comunicator:URLRequest = new URLRequest()
// Creo la FileReference che gestirà le operazioni
var fr:FileReference = new FileReference()
Possiamo ora associare alla variabile fr
gli eventi che vogliamo monitorare: la classe FileReference offre un buon numero di eventi, inoltre possiamo interfacciare un oggetto di tipo FileReference con alcuni eventi di tipoEvent, HTTPStatusEvent, IOErrorEvent e SecurityErrorEvent.
In generale la sintassi per ogni evento è la seguente
oggetto.addEventListener(evento, funzione)
Dove evento è il tipo di evento, mentre funzione è la funzione da richiamare quando l'evento impostato si verifica; ecco quindi come associare i diversi eventi al nostro oggetto FileReference.
Listato 2. Associa gli eventi all'oggetto
// si verifica alla selezione del file
fr.addEventListener(Event.SELECT, selezionato);
// si verifica all'avvio dell'upload
fr.addEventListener(Event.OPEN, aperto);
// si verifica periodicamente e informa sul progresso dell'invio del file
fr.addEventListener(ProgressEvent.PROGRESS, progresso);
// si verifica quando il file è stato completamente inviato
fr.addEventListener(Event.COMPLETE, completo);
// si verifica al completamento dell'upload
fr.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, ritornato);
// si verifica se l'utente annulla la selezione del file
fr.addEventListener(Event.CANCEL, errore);
// si verifica se l'upload non va a buon fine
fr.addEventListener(HTTPStatusEvent.HTTP_STATUS, errore);
// si verifica se si interrompe la comunicazione con il file server-side
fr.addEventListener(IOErrorEvent.IO_ERROR, errore);
// si verifica in caso di conflitti di sicurezza con le impostazioni del player
fr.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errore);
I commenti dovrebbero chiarire il funzionamento dei vari eventi: unica nota per l'evento COMPLETE si verifica quando Flash ha finito di inviare il file allo script PHP, mentre l'evento UPLOAD_COMPLETE_DATA si verifica quando il file PHP restituisce a Flash un messaggio di upload completato sul server. L'evento COMPLETE non garantisce quindi l'avvenuto upload sul server, ma solo il passaggio del file da Flash a PHP, mentre tramite UPLOAD_COMPLETE_DATA saremo sicuri dell'avvenuta copia del file.
Possiamo notare come gli eventi di errore richiamino tutti una medesima funzione, questo perchè gestiremo tutti gli errori allo stesso modo, ovvero eseguendo un comando trace che ci informerà dell'errore; per differenziare il messaggio di output sfrutteremo il tipo di evento che verrà passato automaticamente alla funzione errore. Creiamo allora le varie funzioni per la gestione dei diversi eventi: nel nostro esempio ci limiteremo a mostrare dei messaggi nel pannello di output tramite il comando trace, ovviamente in un progetto lavorativo è consigliato far "reagire" il filmato agli eventi mostrando i messaggi all'utente.
Listato 3. Funzioni per la gestione degli eventi
function errore (evt:*):void {
trace("Errore " + evt.type);
}
function selezionato(evt:Event):void {
trace("Selezionato il file: " + fr.name );
fr.upload(uploader);
}
function aperto(evt:Event):void {
trace("File aperto: " + evt);
}
function progresso(evt:ProgressEvent):void {
trace("Progresso per il file " + fr.name + " - byte caricati: " + evt.bytesLoaded + " - bytes totali:" +
evt.bytesTotal);
}
function completato(evt:Event):void {
trace("Trasferimento completato " + evt);
}
function uploadato(evt:DataEvent) {
trace("L'uploader ha restituito i valori: " + evt.data);
}
Notiamo come ogni funzione abbia un parametro (che abbiamo chiamato evt): tale parametro viene passato automaticamente dagli event listener e contiene alcune informazioni sull'evento che ha lanciato l'azione, notiamo ad esempio che nella funzione errore utilizziamo la proprietà type dell'evento per sapere precisamente quale errore ha richiamato la funzione (ricordiamo infatti che abbiamo impostato la stessa funzione per tutti e 4 i tipi di errore).
Ogni evento ha le sue proprietà, per esempio nella funzione progresso ricaviamo i valori relativi a bytes totali e bytes caricati (bytesTotal e bytesLoaded).
L'oggetto FileReference offre anch'esso diverse proprietà utili per ricavare informazioni sul file che è stato selezionato, per esempio name
restituisce il nome del file (e abbiamo utilizzato tale proprietà nelle funzioni selezionato e progresso), size
indica la dimensione del file, type
ne indica l'estensione, creationDate
la data di creazione, modificationDate
la data dell'ultima modifica e creator l'autore del file.
A questo punto non ci resta che mostrare all'utente la finestra per la selezione del file da uploadare: Flash permette di mostrare una finestra di dialogo dove è anche possibile limitare la selezione solo ad alcuni tipi di file, grazie alla proprietà typeFilter del metodo browse. Il comando per aprire la finestra per la selezione del file è quindi:
fr.browse(tipifile)
Dove il parametro per i tipi di file è opzionale (nel caso non sia specificato verrà mostrata come unica opzione di scelta "Tutti i file (*.*)"; il parametro tipifile è un array ed è possibile creare diversi "set" di file, vediamo un esempio pratico per capire meglio:
var tipifile:Array = [
// Scelta per i file di immagine
new FileFilter("Immmagini (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg; *.jpeg; *.gif; *.png"),
// Scelta per i file di testo
new FileFilter("File di testo (*.doc, *.txt, *.rtf)", "*.doc, *.txt; *.rtf"),
// Scelta per tutti i file
new FileFilter("Tutti i files (*.*)", "*.*")
]
Notiamo che per ogni oggetto FileFilter, il primo parametro è la descrizione che viene visualizzata nella combo di scelta del tipo di file, mentre il secondo parametro è la lista di estensioni che verranno mostrate.
Impostando la variabile tipifile
con il codice appena visto, la finestra per la scelta del file risulterà così:
A questo punto non resta che preparare il file lato server che sposterà fisicamente il file; di seguito viene proposto un possibile codice PHP, ma come già detto il file intermedio può essere in un qualsiasi linguaggio server-side che supporti l'upload.
Listato 4. PHP per caricare il file
<?php
if(isset($_FILES['Filedata']) && isset($_FILES['Filedata']['tmp_name'])) {
if(move_uploaded_file($_FILES['Filedata']['tmp_name'], "destinazione")) {
echo "Upload completato con successo"
}
else {
echo "Impossibile uploadare il file";
}
}
?>
Abbiamo quindi concluso la creazione del nostro uploader: all'avvio del filmato potremo selezionare il nostro file e caricarlo sul server.
Nota: è bene accertarsi che la cartella di destinazione sul server abbia i permessi di scrittura appropriati, altrimenti il file non verrà copiato; in base al server e al nostro hoster potrebbe esserci una cartella dedicata con permessi meno restrittivi (solitamente di nome public).
Download di un file tramite Flash
Molti dei concetti visti per l'upload valgono anche per il procedimento di download, per esempio possiamo sfruttare praticamente gli stessi eventi appena visti (ad eccezione ovviamente di UPLOAD_COMPLETE_DATA).
Impostiamo anche in questo caso le variabili e gli eventi (con le relative funzioni di richiamo):
import flash.net.URLRequest
import flash.net.FileReference
var fr:FileReference = new FileReference()
var downloader:URLRequest = new URLRequest()
// in questo caso viene richiamata quando l'utente sceglie il nome con cui salvare il file scaricato
fr.addEventListener(Event.SELECT,selezionato)
fr.addEventListener(Event.OPEN, aperto);
fr.addEventListener(ProgressEvent.PROGRESS, progresso);
fr.addEventListener(Event.COMPLETE, completo);
fr.addEventListener(HTTPStatusEvent.HTTP_STATUS, errore);
fr.addEventListener(IOErrorEvent.IO_ERROR, errore);
fr.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errore);
function errore (evt:*):void {
trace("Errore " + evt.type);
}
function selezionato(evt:Event):void{
trace("Nome del file che verrà salvato:" + fr.name)
}
function aperto(evt:Event):void {
trace("File aperto: " + evt);
}
function progresso(evt:ProgressEvent):void {
trace("Progresso per il file " + fr.name + " - byte caricati: " + evt.bytesLoaded + " - bytes totali:" +
evt.bytesTotal);
}
function completo(evt:Event):void {
trace("Trasferimento completato " + evt);
}
Anche per l'operazione di download sfrutteremo la classe URLRequest: questa volta specificheremo come parametro URL il percorso del file da scaricare, quindi passeremo l'oggetto URLRequest
creato all'oggetto FileReference.
downloader.url = "File.pdf"
fr.download(downloader,"Scarica.pdf")
Il secondo parametro del metodo download è il nome di default per il file, che verrà mostrato come scelta nella finestra di dialogo aperta dal player; se per l'uplaod infatti il player mostra una finestra di dialogo per scegliere il file da inviare al server, nel caso del download avremo una analoga finestra di dialogo con la possibilità di scegliere la cartella in cui salvare il file e il nome da dargli.
Da notare che dato il limite di una finestra di dialogo alla volta, non potremo invocare più di un metodo upload o download alla volta.