1. Introduzione: archiviazione delle immagini in MySQL
Innanzitutto poniamoci una domanda: รจ possibile allocare immagini sotto forma di informazioni allโinterno di un database? Naturalmente รจ possibile; nello stesso modo sarร possibile gestire queste informazioni, modificarle ed estrarle utilizzando gli stessi comandi SQL che normalmente vengono impiegati per lโamministrazione di stringhe ed interi.
Potremo quindi usare il comando INSERT per lโarchiviazione delle immagini, SELECT per la loro estrazione e cosรฌ via; PHP costituirร unโinterfaccia ideale per automatizzare tutti i processi di amministrazione delle immagini conservate allโinterno di un database, che nel nostro caso sarร un archivio creato tramite il DBMS MySQL.
Ma quali sono i vantaggi nel preferire lโallocazione delle immagini in tabelle piuttosto che in semplici cartelle salvate nella root del Web server? Vediamone alcuni:
- sarร possibile salvare in ogni momento i nostri dati tramite una semplice esportazione (Dump) delle tabelle; รจ certamente molto piรน semplice, veloce e sicuro un singolo comando di esportazione tramite Shell o PhpMyAdmin, piuttosto che il download via FTP di centinaia di file sparsi nel nostro spazio web;
- non sarร piรน possibile accedere direttamente alle immagini tramite URL, con indubbi vantaggi relativi alla sicurezza dei dati.
- non si avranno piรน problemi relativi ai percorsi di accesso alle immagini, queste infatti si troveranno allโinterno di un database raggiungibile attraverso la medesima procedura da una qualsiasi pagina indipendentemente dalla sua posizione;
- non sarร piรน necessario settare permessi sulle cartelle, questo diminuirร lโesigenza di accedere al nostro spazio tramite FTP con conseguente risparmio di tempo.
- lโarchiviazione di file nel database puรฒ comportare dei rischi di insuccesso nellโINSERT e nella SELECT delle informazioni per documenti di grandi dimensioni;
- sarร possibile accedere alle nostre immagini soltanto tramite comandi SQL;
- le immagini mediamente "pesano" molto piรน dei testi e i nostri database diverranno in poco tempo molto ampi.
$sql = 'CREATE TABLE `immagini` ('
. ' `id` int(11) NOT NULL auto_increment,'
. ' `nome` varchar(50) NOT NULL default "",'
. ' `size` varchar(25) NOT NULL default "",'
. ' `type` varchar(25) NOT NULL default "",'
. ' `immagine` blob NOT NULL,'
. ' PRIMARY KEY (`id`)'
. ' )';
Il campo destinato allโallocazione delle immagini sarร quello caratterizzato dal tipo di dato BLOB (Binary Large Object) specificamente dedicato al trattamento di questa tipologia di informazioni.
2. Upload dei file in MySQL
Per lโinvio delle immaginii file nella nostra tabella denominata "immagini", utilizzeremo il classico sistema basato su un form per lโinvio dei parametri di input e di un sorgente PHP dedicato allโelaborazione di questi ultimi.
Nel caso specifico, creeremo una funzione destinata alla raccolta dei dati tramite form e allโinserimento di questi ultimi nel database:
<?
function upload()
{
$result = false;
$immagine = '';
$size = 0;
$type = '';
$nome = '';
$max_size = 300000;
$result = @is_uploaded_file($_FILES['file']['tmp_name']);
if (!$result)
{
echo "Impossibile eseguire l'upload.";
return false;
}else{
$size = $_FILES['file']['size'];
if ($size > $max_size)
{
echo "Il file รจ troppo grande.";
return false;
}
$type = $_FILES['file']['type'];
$nome = $_FILES['file']['name'];
$immagine = @file_get_contents($_FILES['file']['tmp_name']);
$immagine = addslashes ($immagine);
@include 'config.php';
$sql = "INSERT INTO immagini (nome, size, type, immagine) VALUES ('$nome','$size','$type','$immagine')";
$result = @mysql_query ($sql) or die (mysql_error());
return true;
}
}
?>
Lโimpianto della funzione upload() รจ abbastanza semplice, in pratica lo script riceve i dati dal form, controlla che lโupload sia avvenuto correttamente tramite la funzione is_uploaded_file(), quindi, esegue un secondo controllo sulla grandezza dellโimmagine che non deve superare i 30.000 byte.
Una volta eseguite le opportune verifiche, la funzione da il via alla query dโinserimento dei dati allโinterno della tabella. Da notare come le informazioni relative allโimmagine vengano raccolte tramite la superglobale $_FILES, mentre i contenuti binari del file sono estrapolati tramite la funzione file_get_contents().
Nello script viene richiamato, tramite unโinclusione, anche il classico file di configurazione contenente i parametri necessari alla connessione a MySQL e alla selezione del database:
<?
$host = 'localhost';
$username = 'user';
$password = 'password';
$db = 'img';
$conn = @mysql_connect($host,$username,$password) or die (mysql_error());
$sel = @mysql_select_db($db) or die (mysql_error());
?>
3. Form per il caricamento delle immagini in MySQL
Nellโarticolo precedente, abbiamo proposto il codice necessario per la creazione di una funzione destinata alla ricezione di input sotto forma di dati binari e allโinserimento di questi ultimi nella tabella di un database creato tramite MySQL.
Ora descriveremo il listato che potrebbe essere utilizzato per la generazione di un form destinato allโinvio dei parametri di input:
<?
@include 'upload.php';
if (isset($_FILES['file']))
{
upload();
}
echo "
<h3>Upload</h3>
<form enctype=\"multipart/form-data\"
action=\"".$_SERVER['PHP_SELF']."\" method=\"post\">
<input type=\"hidden\" name=\"MAX_FILE_SIZE\"
value=\"300000\" />
<input type=\"file\" name=\"file\" size=\"40\" />
<input type=\"submit\" value=\"Invia\" />
</form>
<br /><a href=\"link.php\">Elenco</a>";
?>
Innanzitutto, viene incluso il file upload.php nel quale abbiamo salvato il codice della funzione per lโelaborazione e lโinserimento dei dati, il lettore potrร tranquillamente utilizzare un nome a suo piacimento, non fร alcuna differenza se lโestensione del file rimane ".php".
In secondo luogo viene effettuato un controllo, infatti, se la variabile superglobale $_FILES รจ stata settata, ciรฒ vuol dire che il parametro di input รจ stato giร inviato e si dovrร procedere con lโallocazione del dato, per far questo si passerร quindi alla chiamata della funzione upload().
In caso contrario, se cioรจ la superglobale non รจ stata valorizzata, verrร visualizzato il form per lโinserimento dei dati.
Il form, nel nostro caso prevederร un unico campo di input destinato al caricamento del file da uploddare. Da notare come per lโinvio di file tramite modulo sia necessario specificare nel delimitatore di apertura del form il costrutto enctype="multipart/form-data", con il quale segnaliamo che i parametri inviati non saranno unicamente testuali.
Nel form troviamo questa specifica name="MAX_FILE_SIZE" value="300000" allโinterno di un campo nascosto, grazie ad essa stabiliamo che i file destinati allโupload non dovranno superare la dimensione massima di 30.000 byte. Questo accorgimento sarร utile per lโutente nel momento in cui dovrร effettuare lโupload, se infatti lโimmagine dovesse essere troppo grande, riceverร immediatamente una notifica indicante lโimpossibilitร di effettuare il caricamento.
Chiuso il form, troviamo un link al file link.php che si occuperร di elencare i link ai file caricati in tabella.
4. Ottenere lโelenco dei file allocati in tabella
Come anticipato nel precedente articolo, una volta eseguito lโupload dei binari in tabella, sarร utile creare un elenco completo dei dati disponibili. Procederemo in questo modo: salveremo in un file, chiamato ad esempio link.php, una query che ci restituirร dei collegamenti alle varie immagini allocate nel database.
I collegamenti saranno relativi ai diversi Id autoincrementali e ognuno di essi farร riferimento al file per la visualizzazione delle immagini di cui parleremo nel capitolo seguente:
<?
@include 'config.php';
$sql = "SELECT id, nome FROM immagini ORDER BY id DESC";
$result = @mysql_query($sql) or die (mysql_error ());
while ($row = @mysql_fetch_array($result))
{
$id = $row['id'];
$nome = $row['nome'];
echo "<a href=\"show.php?id=".$id."\">".$nome."</a><br />";
}
?>
Naturalmente, la nostra prima operazione sarร quella di includere il file di configurazione contenente i parametri necessari per la connessione al DBMS e alla selezione del nostro database.
In secondo luogo, verrร operata una query di selezione con la quale estrarremo lโId e il nome di ogni binario inserito in tabella.
Lโordine della selezione, รจ stato imposto per comoditร espositiva in senso decrescente (DESC) rispetto allโautoincrementale, in ogni caso, nulla vieta al lettore di modificare la logica dellโinterrogazione ordinando i dati secondo una campo differente (ad esempio il nome del file), oppure di imporre un limite al numero dei record estratti tramite la calusola LIMIT.
Una volta effettuata lโinterrogazione, verranno elencati i link ad ogni immagine, il file destinato alla loro visualizzazione (show.php) raccoglierร da una querystring lโId inviato tramite link.php in modo da mostrare lโimmagine corrispondente ad esso.
5. Visualizzare file da una tabella MySQL
Passiamo ora allโultima parte del nostro discorso riguardante la gestione delle immagini con PHP e MYSQL; ci accingiamo a creare una pagina attraverso la quale visualizzare le immagini contenute nel nostro database.
<?
if (isset($_GET['id']))
{
$id = @intval($_GET['id']);
@include 'config.php';
$sql = "SELECT id,type,immagine FROM immagini WHERE id='$id'";
$result = @mysql_query($sql) or die(mysql_error ());
$row = @mysql_fetch_array($result);
$id_img = $row['id'];
$type = $row['type'];
$img = $row['immagine'];
if (!$id_img)
{
echo "Id sconosciuto";
}else{
@header ("Content-type: ".$type);
echo $img;
}
}else{
echo "Impossibile soddisfare la richiesta.";
}
?>
Innanzitutto lo script controlla lโinvio dellโId da parte della pagina/elenco e solo se questo รจ stato raccolto dร vita al processo di visulizzazione.
Nel corso del listato vengono effettuati altri due controlli: il primo verifica lโId attraverso la funzione intval() che estrae il valore intero da una variabile; il secondo convalida lโId inviato, non sarร quindi possibile inviare alla query Id non registrati in tabella.
Una volta effettuati i controlli previsti, lo script esegue unโinterrogazione al database sulla tabella delle immagini richiedendo lโestrazione dei dati relativi allโId inviato in querystring tramite il metodo GET; quindi si procede alla stampa a video del file richiesto.
Da notare come la soddisfazione della rchiesta di visualizzazione necessiti che venga specificato nellโHeader dellโoutput il Content-type relativo alla tipologia di immagine che vogliamo mostrare; per fare un esempio, unโimmagine JPEG sarร specificata da un Content-type sul modello del seguente:
Content-type: image/jpeg