Upload di immagini in Php-MySQL Con questo articolo invece vediamo come utilizzare il PHP per effettuare l'upload, modificare e cancellare immagini da un database MySQL. L'esempio tratta immagini ed swf, ma è facilmente adattabile a qualsiasi tipo di file. Parte del codice che ho utilizzato per scrivere questo tutorial è tratto dall'articolo "File uploads made easy" di Darren Beale, ma in buona parte è stato modificato per interfacciarlo ad un database. L'esempio, che potete scaricare cliccando sul tasto per il download, è formato da 2 files php: - upload.php - getdata.php Il file principale è il primo, dato che contiene tutto il codice per la gestione delle immagini. Da premettere che i file sono perfettamente funzionanti (a condizione di una giusta configurazione dei parametri di connessione al db), ma per comprendere appieno il codice occorre avere già una infarinata di PHP, dato che non mi soffermerò troppo sul significato dei comandi utilizzati. La prima cosa da fare è definire una serie di variabili globali (come l'esempio di Beale): $my_max_file_size = "307200"; //sarebbero 300Kb $image_max_width = "400"; // in pixel $image_max_height = "500"; // in pixel $registered_types = array( "application/x-gzip-compressed" => ".tar.gz, .tgz", "application/x-zip-compressed" => ".zip", "application/x-tar" => ".tar", "text/plain" => ".html, .php, .txt, .inc", "image/bmp" => ".bmp, .ico", "image/gif" => ".gif", "image/pjpeg" => ".jpg, .jpeg", "image/jpeg" => ".jpg, .jpeg", "application/x-shockwave-flash" => ".swf", "application/msword" => ".doc", "application/vnd.ms-excel" => ".xls", "application/octet-stream" => ".exe, .fla" ); Di tutte queste ne utilizziamo solo le seguenti: $allowed_types = array("image/gif","image/pjpeg","image/jpeg","application/x-shockwave-flash"); Seguono poi tutte una serie di funzioni che verranno utilizzate a seconda delle operazioni da svolgere. In realtà la prima istruzione che viene eseguita si trova alla riga 201: dbconnect(); Richiama la funzione relativa alla connessione al database MySQL: function dbconnect() { mysql_connect("db_host", "db_username", "db_password"); @mysql_select_db("db_name") or die ("Unable to select database"); } Sono le uniche righe da configurare per il corretto funzionamento del programma. Nel database, creiamo una tabella che chiameremo mmkit_images con i seguenti campi: id int(11) NOT NULL auto_increment, bin_data longblob, filename varchar(255), filesize varchar(50), filetype varchar(50), filewidth varchar(50), fileheight varchar(50), PRIMARY KEY (id) che contengono rispettivamente i dati binari del file, il nome, la dimensione in byte, il tipo di file (jpg, gif, swf), la larghezza e l'altezza. Nell'allegato è presente un file SQL, che se eseguito (ad esempio con phpMyAdmin) crea in automatico la tabella ed i relativi campi. Ritornando al file upload.php, segue uno switch per richiamare la funzione desiderata: switch($task) { case 'upload': upload($thefile); break; case 'delete': delete($id); break; case 'mod': mod($id); break; case 'change': change($thefile, $id); break; default: form($error); } Appena partiamo la funzione richiamata è form(), dove è presente la form per l'invio delle immagini. Il codice HTML è il seguente:

File:

La prima cosa da notare è che per poter inviare file al server è necessaria una form con il parametro ENCTYPE="multipart/form-data". É importante anche il campo che definisce la dimensione massima del file da inviare. Da notare che comunque non sempre basta questo parametro per evitare l'upload di file giganteschi (infatti controlleremo sempre il file che arriva al server prima di inserirlo nel db), ma è una riga necessaria per il corretto funzionamento dell'upload. Fate poi attenzione a non alzare troppo questo valore: in genere un database MySQL di default può accettare dati per un massimo di 2Mb per ogni campo LONGBLOB, ma può essere settato anche a meno. Quindi per conoscere qual è la dimensione massima dei file che potete inserire nel db dovete contattare l'amministratore del server che vi fornisce il servizio. In genere si può arrivare senza problemi a gestire file di 8Mb, ma sinceramente non ho mai provato. La form punta sempre al file upload.php, ma come campo hidden abbiamo la variabile task=upload, che tramite lo switch visto poc'anzi richiamerà la funzione upload(). Una cosa molto interessante è che con questo tipo di form, il file inviato lo ritroviamo nella variabile $thefile, ma con esso ritroviamo in automatico anche le seguenti variabili (tutte global): $thefile_name, $thefile_size, che contengono il nome del file e la sua dimensione (in byte). Per sapere invece le dimensioni in pixel dell'immagine basta eseguire: $size = GetImageSize($thefile); questa funzione restituisce (in una serie di valori contenuti in un array) le dimensione di immagini GIF, JPG, PNG, SWF, SWC, PSD, TIFF, BMP e IFF. Per maggiori info php.net. Preleviamo le variabili che ci interessano con un list: list($foo,$width,$bar,$height) = explode(""",$size[3]); così da avere in $width e $height la larghezza e l'altezza del file. Delle altre variabili possiamo farne a meno. Detto questo possiamo capire il funzionamento della funzione upload(): per prima cosa viene eseguito un test tramite la funzione validate_upload() per controllare se la dimensione in byte o in pixel dell'immagine sia contenuta nei limiti che abbiamo prefissato. Per i file swf (data la loro natura vettoriale), invece ho inserito un ridimensionamento automatico se le dimensioni risultano maggiori di quelle stabilite. Le nuove variabili globali $g_height e $g_width vengono quindi settate alle dimensioni da inserire nel database. Se l'immagine è accettata viene letta ed inserita nel db tramite questo codice: $fp=@fopen($thefile, "r"); if ($fp){ $data = addslashes(fread($fp, filesize($thefile))); $result=MYSQL_QUERY("UPDATE mmkit_images SET bin_data='$data', filename='$thefile_name', filesize='$thefile_size', filetype='$thefile_type', filewidth='$g_width', fileheight='$g_height' WHERE id=$id"); fclose($fp); if (!$result) { echo mysql_errno(). ": ".mysql_error(). " "; exit();} else Header("Location: upload.php"); } else { ...errore... } Viene letto il file con il comando fopen (il @ prima di esso fa in modo di non stampare un messaggio di errore in caso di problemi... solamente per una sorta di pulizia del risultato dato che tutti i messaggi di errore sono inseriti con un echo), e dopo aver spostato il contenuto nella variabile $data viene inserito nel database con una query. Se tutto è andato bene si viene reindirizzati su upload.php, altrimenti viene stampato un errore. Per visualizzare le immagini invece c'è la funzione list_files(): function list_files() { $result=mysql_query("select id, filename, filetype, filewidth, fileheight from mmkit_images"); if (mysql_num_rows($result) > 0) { echo""; while(list($id, $filename, $filetype, $width, $height)=mysql_fetch_row($result)) { echo""; if (ereg("flash", $filetype)) { echo""; } else { echo""; } } echo"
Files presenti nel database:
Delete - Modify
"; } else echo"
Il database è vuoto."; } Vengono presi tutti i record presenti nella tabella e viene stampato un codice HTML diverso a seconda se il file che dobbiamo visualizzare è di tipo immagine o di tipo Flash. Notiamo che nei relativi attributi src è inserito il file getdata.php?id=$id. Questo file è quello delegato a prendere i dati binari e a creare un header adatto. Il codice del file getdata.php è tutto qui: function dbconnect() { mysql_connect("db_host", "db_username", "db_password"); @mysql_select_db("db_name") or die ("Unable to select database"); } dbconnect(); if($id) { $query = "select bin_data, filetype FROM mmkit_images WHERE id='$id'"; $result = @MYSQL_QUERY($query); $data = @MYSQL_RESULT($result,0,"bin_data"); $type = @MYSQL_RESULT($result,0,"filetype"); Header("Content-type: $type"); echo $data; }; Infatti dopo la connessione al database, viene prelevata l'immagine ed il relativo filetype e viene inviato un nuovo content-type relativo al tag html che si sta eseguendo ed il suo contenuto. Una volta che eseguite i files in allegato troverete anche la possibilità di eliminare o di cambiare un'immagine. Il codice è piuttosto semplice (si tratta solamente di eseguire delle query): $result=MYSQL_QUERY("UPDATE mmkit_images SET bin_data='$data', filename='$thefile_name', filesize='$thefile_size', filetype='$thefile_type', filewidth='$g_width', fileheight='$g_height' WHERE id=$id"); per l'aggiornamento di un'immagine e mysql_query("delete from mmkit_images WHERE id=$id"); per la sua cancellazione. Vi ricordo che per un corretto funzionamento dei files in allegato, il server che userete deve supportare il PHP, dovete avere accesso ad un database MySQL su cui dovete aver creato la tabella con le caratteristiche presenti nel file mmkit_images.sql (basta eseguirlo con phpMyAdmin oppure con una query in php) e dovete configurare i parametri di connessione al db nei file upload.php (righe 28-29) e getdata.php (righe 3-4). Inoltre i file upload.php e getdata.php si devono trovare nella stessa directory. Il codice inoltre si presta alla possibilità di usare e gestire anche altri tipi di file (.zip ad esempio): basta fare poche modifiche ed eliminare la parte relativa alle dimensionamento in pixel del file. La sintassi usata nell'esempio considera la variabile register_globals su on. Dato che la sintassi è già indicata come deprecated, conviene usare le variabili super global per la gestione delle variabili provenienti da una form. Quindi le vairabili provenienti dalla form per la selezione del file vanno presi e gestiti con $_REQUEST o $_POST (ad esmepio $_POST['task'], invece di $task), mentre il file viene gestito con la variabile $_FILES: $thefile_name diventa $_FILES['thefile']['name'] $thefile_size diventa $_FILES['thefile']['size'] $thefile_type diventa $_FILES['thefile']['type'] Per maggiori info sulla variabile $_FILES clicca qui (http://it.php.net/manual/en/features.file-upload.php#features.file-upload.post-method)