[AS3] Upload con Flash e PHP
Utilizzo della classe FileReference
Inserito il 02-02-2008
Rispetto alla sua introduzione in Flash 8, la classe FileReference non è stata modificata più di tanto nella procedura di utilizzo, ma chiaramente in AS3 segue il monitoraggio degli eventi secondo la classe EventDispatcher e l'event handling. L'integrazione più importante è stata senz'altro la possibilità di gestire, tra gli altri eventi, un ritorno da parte dello script di upload, che desse ad actionscript una conferma o meno sulla riuscita del caricamento sul server del file scelto.
Aggiungo, per completezza di informazione, che lo stesso evento è stato aggiunto anche in AS2, ma è utilizzabile solo se si pubblica per una versione di flash player pari o superiore alla 9.0.28.0 (evento onUploadCompleteData)
Vediamo ora un codice tipo per la gestione degli upload in flash, interamente commentato:
Il seguente codice, incluso dei commenti, è liberamente tratto da un codice di esempio di Andrea Giammarchi, e riadattato alla versione 3 di Actionscript, con aggiunta dell'evento di verifica dell'upload avvenuto (DataEvent.UPLOAD_COMPLETE_DATA).
// Nome del file di gestione upload lato server var url:String = "http://www.[dominio].com/file_upload.php"; // istanza di URLRequest che gestisce la comunicazione con il file esterno var request:URLRequest = new URLRequest(url); // inizializzazione dell'istanza di FileReference var file:FileReference = new FileReference(); /* configurazione degli eventi associati all'upload del file inseriti nell'ordine in cui vengono richiamati se non ci sono intoppi */ file.addEventListener(Event.SELECT, select); // selezione del file nella finestra di upload file.addEventListener(Event.OPEN, open); // inizio di upload del file file.addEventListener(ProgressEvent.PROGRESS, progress); // descrizione del progresso richiamata periodicamente durante l'upload file.addEventListener(Event.COMPLETE, complete); // completamento della trasmissione del file al server, completato file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, uploadCompleteData); // verifica delle informazioni ricevute dal server sull'avvenuto upload nel server // configurazione degli eventi associati ad eventuali errori o scelte dell'utente che bloccano l'upload del file file.addEventListener(Event.CANCEL, error); // richiamato nel caso che venga cliccato "Annulla" nella finestra di scelta del file file.addEventListener(HTTPStatusEvent.HTTP_STATUS, error); // richiamato nel caso di errore generato dal fallimento nell'upload file.addEventListener(IOErrorEvent.IO_ERROR, error); // richiamato se l'upload fallisce per errore di comunicazione con il file di upload lato server file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, error); // richiamato in caso di violazione delle regole di sicurezza del flash player // Funzione richiamata dagli eventi che provocano errore function error (event:*):void { trace("Errore di tipo: " + event.type); } // Funzione richiamata quando il file viene selezionato function select(event:Event):void { trace("select function: name=" + file.name + " URL=" + request.url); file.upload(request); } // Funzione richiamata ad inizio upload (o download) function open(event:Event):void { trace("open function: " + event); } // Funzione richiamata dopo onOpen ad upload / download cominciato function progress(event:ProgressEvent):void { trace("progress function name=" + file.name + " bytesLoaded=" + event.bytesLoaded + " bytesTotal=" + event.bytesTotal); } /* Funzione richiamata ad upload / download terminato. Il file sul server avra' gia' elaborato quando questo metodo verra' richiamato. */ function complete(event:Event):void { trace("complete function : " + event); } /* Funzione richiamata ad upload elaborato e terminato sul server * L'evento contiene al suo interno una proprietà "data" che contiene la risposta del server * e che è utile elaborare nel caso si voglia avere una conferma dell'upload avvenuto * utile ad esempio nel caso che si voglia verificare che un determinato file non esista già * sul server e nel caso mostrare un warning all'utente */ function uploadCompleteData (event:DataEvent) { trace("upload return data function : " + event); trace("data received : " + event.data); } /* Array per specificare il tipo di dati da visualizzare per l' upload * L' array sarà composto da tante istanze di FileFilter quanti sono i tipi differenti di files da voler far uploadare. * Ogni FileFilter sarà composto da due parametri di tipo stringa che rappresenteranno rispettivamente * la descrizione del tipo di file) e le estensioni valide per quel tipo di file separate da ";" */ var filetype:Array = [ // Esempio alcuni tipi di immagini new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg; *.jpeg; *.gif; *.png"), // Esempio files di testo new FileFilter("Text Files (*.txt, *.rtf)", "*.txt; *.rtf"), // Esempio specifico di un unico file new FileFilter("Specific File (test.swf)", "test.swf"), // Esempio tutti i files new FileFilter("All Files (*.*)", "*.*")] // comando da usare quando vogliamo sfruttare l' upload file.browse(filetype);
Alla stessa maniera presentiamo il codice PHP che andrà ad operare l'effettiva copia del file sul server:
La premessa è la stessa di prima, il codice varia rispetto alla versione originale solo per il diverso metodo di conferma dell'upload allo script dell'swf.
<?php // 4, compatibile 5.0 e 5.1 // Directory di destinazione $destination_dir = ''; // Verifico che il file sia valido e come lui tutte le informazioni // Controllo inoltre che non ci siano errori nell' invio ... altrimenti non faccio niente if( // esiste il file di nome Filedata ? isset($_FILES['Filedata']) && // é un array ? is_array($_FILES['Filedata']) && // esistono gli elementi tmp_name, name, size, error // di questo array ? isset( $_FILES['Filedata']['tmp_name'], $_FILES['Filedata']['name'], $_FILES['Filedata']['size'], $_FILES['Filedata']['error'] ) && // l' errore é esattamente zero ? intVal($_FILES['Filedata']['error']) === 0 ) { // operazione di spostamento da temporanea ad altra cartella // se riesco a spostare il file sulla destinazione scrivo un tipo di output if(move_uploaded_file($_FILES['Filedata']['tmp_name'], $destination_dir.$n)) { echo "result=successfull uploaded&date=".date('Y-m-d H:i:s')."&filename=$n&size={$_FILES['Filedata']['size']}"; } // altrimenti scrivo un altro tipo di output else { echo "result=unable to move file&date=".date('Y-m-d H:i:s')."&filename={$_FILES['Filedata']['name']}&size={$_FILES['Filedata']['size']}&error={$_FILES['Filedata']['error']}"; } } ?>
I commenti sui due codici dovrebbero essere abbastanza esaustivi riguardo a quello che fanno gli script, sia sul lato client (flash) che su quello server (php).
Non entro poi nel merito della questione permessi cartella su server Linux o Windows, ma in generale, con il codice sopra descritto, se funziona l'upload attraverso un form html, funziona anche questo... perciò se ci sono problemi di funzionamento di questo upload, vi consiglio di fare un test attraverso un form html semplice per capire se il problema dipende dall'uso di flash per l'upload o da restrizioni da parte del vostro provider
Un'ultima nota a margine: in alcuni server la sicurezza nella gestione degli upload, potrebbe bloccare a metà il lavoro dello script e restituirvi un http status pari a 500 (Internal server error) e un errore #2038 su Flash. Nella maggior parte dei casi il problema è dovuto al "mod_security", del quale preferisco non approfondire e vi lascio trovare soluzione su internet, a seconda del vostro server e caso specifico.
Lascio a voi gli utilizzi, le prove e quant'altro, sperando come sempre di aver per lo meno dato un input utile all'approfondimento.
