Redazione
a- a+

L'upload dei files

Essere in grado di accettare gli uploads dai vostri utentiè una di quelle funzioni sorprendentemente essenzialiche si incontrano in diverse applicazioni.
Gli esempi sono dappertutto: nei bullettin board, allepersone è spesso permesso di allegare file, gli scriptdi gestione di un sito web spesso permettono agli utenti dicreare o aggiungere nuovi file, etc.
Aggiungere l'uploads di file nei vostri script èrelativamente semplice, infatti l'HTML include questafunzione: <input type="file"name"file">.
Quando però includiamo questo campo in un form,bisognerà aggiungere un altro attributo:enctype="multipart/form". Questo dice al browserche, oltre al testo standard, un file potrebbe essereallegato e spedito con il form.

Diamo un'occhiata ad una semplice pagina che contiene unform:

 

<html><head></head><body><form action="<?=$PHP_SELF?>" method="post" enctype="multipart/form-data"><br><br>Choose a file to upload:<br><input type="file" name="file"><br><input type="submit" name="submit" value="submit"></form></body></html>

 

Nel tag "form action" , il metodo deve sempreessere POST e non GET.
Se l'utente seleziona un file e conferma il form, ilfile verrà caricato e salvato in una directorytemporanea sul server, con un nome temporaneo.
Ed è qui che inizia la vera programmazione.

ACCEDERE AI FILE CARICATI
Proprio come altri elementi del form, il valore del campo"file" può essere accessibile con il nomedella variabile che coincide con il nome dell'input, inquesto caso "file".
Altrimenti si possono usare altre variabili che contengonomaggiori informazioni, come nella lista qui sotto:

$HTTP_POST_FILES['file']

"file" è il nome file inserito nel form

$HTTP_POST_FILES['file']['name']

il nome originale del file dal computer dell'utente

$HTTP_POST_FILES['file']['tmp_name']

nome temporaneo del file quando viene caricato

$HTTP_POST_FILES['file']['type']

il nome del file generato dal browser dell'utente

$HTTP_POST_FILES['file']['size']

la dimensione del file, in byte

 

CONVALIDA

Di solito ci sono tre controlli che dovrebbero essereeffettuati sui file in entrata:

1. Il file è stato effettivamente caricato?
2. Il file ha una grandezza che rientra nei limitispecificati?
3. Il tipo di file rientra in quelli da noi specificati?

E' possibile anche creare dei simpatici messaggi dierrore personalizzati, nel caso in cui il file caricato noncorrisponda a uno dei 3 controlli sopra citati.

Il modo più sicuro e corretto per controllare se unfile è stato caricato è l'utilizzo diis_uploaded_file(), disponibile con PHP3, PHP4.02 osuperiore.
Diamo un'occhiata a come farlo:

if (!is_uploaded_file($HTTP_POST_FILES['file']['tmp_name'])) {$error = "You did not upload a file!";unlink($HTTP_POST_FILES['file']['tmp_name']);} else {//a file was uploaded}

La dichiarazione "if" controlla se un file èstato creato con il nome specificato e in caso affermativo ilfile viene caricato.
Se il file è stato caricato, allora il contenutodella dichiarazione "else" verràeseguito.
La cosa seguente che dobbiamo convalidare è ladimensione del file. 
Per esempio, diciamo che volete accettare solo files sotto i10Kb.
Per prima cosa dovete assegnare la dimensione massimaaccettabile del file in una variabile (in bytes) e poicontrollare la dimensione reale del file da caricare.
Vediamo in pratica come fare:

$maxfilesize=10240;if ($HTTP_POST_FILES['file']['size'] > $maxfilesize) {$error = "file is too large";unlink($HTTP_POST_FILES['file']['tmp_name']);} else {//the file is under the specified number of bytes.}

 

Se il file caricato fallisce il controllo, allora genereremoun messaggio di errore e verrà terminato il processodel form.
Con la funzione "unlink" andiamo a rimuovere ilfile dal server se si è verificato un errore,così da permettere al file di essere caricato consuccesso.
Il controllo finale riguarda il tipo di file.Non bastaandare a controllare l'estensione del file chel'utente va a caricare, perché potrebbe esserealterato o rinominato.
Per una maggiore sicurezza bisogna usare la variabile$HTTP_POST_FILES['file']['type'].
Facciamo un esempio e andiamo a controllare che il filecaricato sia un .JPG o .GIF

if($HTTP_POST_FILES['file']['type'] != "image/gif" AND $HTTP_POST_FILES['file']['type'] != "image/pjpeg" AND $HTTP_POST_FILES['file']['type'] !="image/jpeg") { $error = "This file type is not allowed";unlink($HTTP_POST_FILES['file']['tmp_name']);} else {//the file is the correct format}

Anche in questo caso, se il controllo fallisce, dobbiamogenerare un messaggio d'errore e rimuovere il filecaricato dal server.
Se invece, il file supera il controllo, allora lo andremo acopiare nella destinazione finale, cambiandogli nome oppureusando quello originale datogli dall'utente operando inquesto modo:

copy($HTTP_POST_FILES['file']['tmp_name'],"/finallocation/".$HTTP_POST_FILES['file']['name']);

Dopo che il file è stato copiato nella posizionefinale, andiamo a rimuovere il file temporaneo:

unlink($HTTP_POST_FILES['file']['tmp_name']);

Ultimo controllo da effettuare, è quello riguardanteil tasto di conferma (submit) e quindi verificare chel'utente dopo aver scelto il file da caricare, abbiaeffettivamente premuto questo tasto.
Guardiamo l'intero codice:

<?phpif ($HTTP_POST_VARS['submit']) {print_r($HTTP_POST_FILES);if (!is_uploaded_file($HTTP_POST_FILES['file']['tmp_name'])) {$error = "You did not upload a file!";unlink($HTTP_POST_FILES['file']['tmp_name']);// assign error message, remove uploaded file, redisplay form.} else {//a file was uploaded$maxfilesize=10240;if ($HTTP_POST_FILES['file']['size'] > $maxfilesize) {$error = "file is too large";unlink($HTTP_POST_FILES['file']['tmp_name']);// assign error message, remove uploaded file, redisplay form.} else {if ($HTTP_POST_FILES['file']['type'] != "image/gif" AND $HTTP_POST_FILES['file']['type'] != "image/pjpeg") { $error = "This file type is not allowed";unlink($HTTP_POST_FILES['file']['tmp_name']);// assign error message, remove uploaded file, redisplay form.} else {//File has passed all validation, copy it to the final destination and remove the temporary file:copy($HTTP_POST_FILES['file']['tmp_name'],"/finallocation/".$HTTP_POST_FILES['file']['name']);unlink($HTTP_POST_FILES['file']['tmp_name']);print "File has been successfully uploaded!";exit;}} }}?><html><head></head><body><form action="<?=$PHP_SELF?>" method="post" enctype="multipart/form-data"><?=$error?><br><br>Choose a file to upload:<br><input type="file" name="file"><br><input type="submit" name="submit" value="submit"></form></body></html>

Per bloccare lo script, dopo un upload avvenuto con successo,e rivisualizzare il form per il prossimo upload, dobbiamoaggiungere un messaggio che avverta l'utente che il fileè stato accettato e poi uscire dallo script.
Se invece il file non è stato caricato con successo,il form verrà rivisualizzato e aggiungendo una nuovaline di codice php all'interno del form HTML saràpossibile avvertire l'utente del perché il filenon è stato accettato.

QUANDO IL FILE CARICATO NON FUNZIONA

Errori di logica a parte, ci sono alcuni problemi che possonoaccadere quando si lavora con i file caricati. Se sieteappena all'inizio con lo studio di PHP, trovarsi difronte a questi problemi può rivelarsi davverofrustrante.
Fortunatamente la maggior parte di questi problemi non sonoirrisolvibili e hanno anzi una diretta soluzione:

1. Il file non viene caricato, e non viene segnalatol'errore
Partendo dal presupposto che il codice è corretto,questo problema si verifica molto spesso quando si fal'upload di files di grandi dimensioni. Oltre allelimitazioni della grandezza del file che imponente durante lafase di convalida sul lato server, ci sono anche alcunisettaggi nel file PHP.ini, che riguardano la grandezzamassima del file caricato.Questi settaggi non tengono contodelle opzioni che sono state specificate nello script.
Se un piccolo upload di un file di pochi KB ha successo,mentre uno più grande di qualche MB fallisce, ci sonobuone probabilità che questo sia il problema.
Se invece utilizzate un vostro server e avete accesso alfile PHP.ini, è possibile andare a cambiare ladimensione massima del file, modificando l'attributoupload_max_filesize.
Inoltre controllare anche l'attributo memory_limit chenon abbia un valore troppo basso.

2. Il file non viene copiato nella destinazione finale,errore di permesso negato
Questo errore accade nei server *nix quando il file non hal'accesso di scrittura nella directory specificata.
I permessi nei server *nix riguardano chi può leggeree scrivere nelle directories e nei files e sono divisi in tregruppi: proprietario, gruppo, altro.
I permessi possono essere regolati dalla maggior parte deiprogrammi FTP.
Per le directories dove i file devono essere scritti, ipermessi vanno regolati su 666 o 777.

3. I file non vengono caricati o non possono essere copiati,vengono mostrati questi messaggi di errore:"open_basedir restriction in effect" , "SafeMode Restriction in effect" oppure "la funzioneè stata disabilitata per motivi disicurezza".
Questo tipo di errore è comune a quegli script chelavorano su web hosting providers condivisi e indica che PHPsta lavorando in modo protetto (Safe Mode).
Il modo protetto permette agli amministratori di sistema dicontrollare quali utenti sono abilitati e quali funzionidisabilitare per motivi di sicurezza.
Senza l'accesso al file PHP.ini, il modo protettopuò essere disattivato dall'amministratore disistema.

ALTRE NOTE SULL'UPLOAD DEI FILES
A causa di alcuni cambiamenti in PHP, effettuati nelleultime versioni, alcuni aspetti nel lavorare con l'uploaddei files può variare.
Ecco alcune cose da tenere bene a mente:

1. Nella versione PHP 4.2.0 è stato introdotto unnuovo elemento nella stringa $HTTP_POST_FILES che restituisceuno specifico messaggio di errore se l'upload del filefallisce. Viene utilizzato in questo modo:

$HTTP_POST_FILES['file']['error'] 

e restituisce quanto segue:
0: nessun errore, il file è stato caricato consuccesso
1: l'upload del file ha una dimensione maggiore rispettoa quanto indicato nella stringa upload_max_filesize delphp.ini
2: l'upload del file ha una dimensione maggiore rispettoa quanto indicato nella stringa max_file_size del codiceHTML
3: Il file è stato caricato solo parzialmente
4: Nessun file è stato caricato
Questi messaggi sono particolarmente utili per il controllodegli errori e per determinare il successo o il fallimentodel caricamento di un file, ma siccome sono solo supportatedalle nuove versioni di PHP, non potete fare affidamentosulla loro esistenza se programmate script per ladistribuzione.

2. I nomi esatti della variabili che sono usate per riferirsiai file caricati dipende dalla versione dalla configurazionedi PHP.
La stringa $HTTP_POST_FILES è disponibile dallaversione 4.0, ma nelle ultime versioni si utilizza unastringa più corta : $_FILES.
Nelle configurazioni dove register_globals è settatosu "on" , la stringa $HTTP_POST_FILES puònon essere disponibile e i file caricati possono essereaccessibili come:
$file nome temporaneo del file quando viene caricato
$file_name il nome originale del file preso dal computerdell'utente
$file_type il tipo di file, come previsto dal browserdell'utente
$file_size la dimensione del file in byte

3. is_uploaded_file() non è disponibile in tutte leversione di PHP: se siete così sfortunati da usare unaparticolare versione di PHP che non supporta questa funzione,potete controllare se un file è stato caricato oppureno, guardando se il nome temporaneo del file e uguale a"none" oppure "empty"

if ($HTTP_POST_FILES['file']['tmp_name']=="none" OR $HTTP_POST_FILES['file']['tmp_name']="") {//no file uploaded}

Inoltre per gestire la dimensione del file durante la fase diconvalida dal lato server, potete specificare la dimensionemassima usando un campo nascosto dentro il form in questomodo:

<input type="hidden" name="MAX_FILE_SIZE" value="1000">

Ricordate però che questo attributo è solo unsuggerimento e non attendibile al 100%.

INFINE

In questo articolo avete avuto un assaggio di come lavorarecon l'upload dei files. 
Le cose da ricordare sono:
* Quando create un form che include il campo "fileupload" , dovete includere nel tag:enctype="multipart/form-data" così da direal browser che c'è un upload e settare il metododel form su POST
* In molte configurazioni, il file caricato saràdisponibile in una stringa $http_post_vars con lo stesso nomedel file assegnato nel campo "file upload"
* Quando accettate l'upload di files, generalmentedovete fare 3 controlli: se il file è stato caricatooppure no; la dimensione del file caricato; il tipo di filecaricato
* Il file temporaneo deve essere cancellato con la funzioneunlink() dopo che il file è stato copiato nelladestinazione finale oppure se l'upload del file fallisceuno dei 3 controlli sopra elencati.