Programmazione
Asp
Asp.NET
Java
Javascript
Php
Oracle

Svaghi
Ascolta Radio
Faccine
Libri
Links

Varie
Cerca nel sito...
Segnalazioni
Scrivimi


Upload di files

Essere in grado di accettare gli uploads dai vostri utenti è una di quelle funzioni sorprendentemente essenziali che si incontrano in diverse applicazioni.
Gli esempi sono dappertutto: nei bullettin board, alle persone è spesso permesso di allegare file, gli script di gestione di un sito web spesso permettono agli utenti di creare o aggiungere nuovi file, etc.
Aggiungere l'uploads di file nei vostri script è relativamente semplice, infatti l'HTML include questa funzione: <input type="file" name"file">.
Quando però includiamo questo campo in un form, bisognerà aggiungere un altro attributo: enctype="multipart/form". Questo dice al browser che, oltre al testo standard, un file potrebbe essere allegato e spedito con il form.
Diamo un'occhiata ad una semplice pagina che contiene un form:

<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 sempre essere POST e non GET.
Se l'utente seleziona un file e conferma il form, il file verrà caricato e salvato in una directory temporanea sul server, con un nome temporaneo.
Ed è qui che inizia la vera programmazione.

ACCEDERE AI FILES CARICATI
Proprio come altri elementi del form, il valore del campo "file" può essere accessibile con il nome della variabile che coincide con il nome dell'input, in questo caso "file".
Altrimenti si possono usare altre variabili che contengono maggiori 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 essere effettuati sui file in entrata:

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

E' possibile anche creare dei simpatici messaggi di errore personalizzati, nel caso in cui il file caricato non corrisponda a uno dei 3 controlli sopra citati.
Il modo più sicuro e corretto per controllare se un file è stato caricato è l'utilizzo di is_uploaded_file(), disponibile con PHP3, PHP4.02 o superiore.
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 il file viene caricato.
Se il file è stato caricato, allora il contenuto della dichiarazione "else" verrà eseguito.
La cosa seguente che dobbiamo convalidare è la dimensione del file.
Per esempio, diciamo che volete accettare solo files sotto i 10Kb.
Per prima cosa dovete assegnare la dimensione massima accettabile del file in una variabile (in bytes) e poi controllare 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 genereremo un messaggio di errore e verrà terminato il processo del form.
Con la funzione "unlink" andiamo a rimuovere il file dal server se si è verificato un errore, così da permettere al file di essere caricato con successo.
Il controllo finale riguarda il tipo di file.Non basta andare a controllare l'estensione del file che l'utente va a caricare, perché potrebbe essere alterato o rinominato.
Per una maggiore sicurezza bisogna usare la variabile $HTTP_POST_FILES['file']['type'].
Facciamo un esempio e andiamo a controllare che il file caricato 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, dobbiamo generare un messaggio d'errore e rimuovere il file caricato dal server.
Se invece, il file supera il controllo, allora lo andremo a copiare nella destinazione finale, cambiandogli nome oppure usando quello originale datogli dall'utente operando in questo modo:

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

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

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

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

<?php
if ($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, dobbiamo aggiungere 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 nuova line di codice php all'interno del form HTML sarà possibile avvertire l'utente del perché il file non è stato accettato.

QUANDO IL FILE CARICATO NON FUNZIONA

Errori di logica a parte, ci sono alcuni problemi che possono accadere quando si lavora con i file caricati. Se siete appena all'inizio con lo studio di PHP, trovarsi di fronte a questi problemi può rivelarsi davvero frustrante.
Fortunatamente la maggior parte di questi problemi non sono irrisolvibili e hanno anzi una diretta soluzione:

1. Il file non viene caricato, e non viene segnalato l'errore
Partendo dal presupposto che il codice è corretto, questo problema si verifica molto spesso quando si fa l'upload di files di grandi dimensioni. Oltre alle limitazioni della grandezza del file che imponente durante la fase di convalida sul lato server, ci sono anche alcuni settaggi nel file PHP.ini, che riguardano la grandezza massima del file caricato.Questi settaggi non tengono conto delle 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 sono buone probabilità che questo sia il problema.
Se invece utilizzate un vostro server e avete accesso al file PHP.ini, è possibile andare a cambiare la dimensione massima del file, modificando l'attributo upload_max_filesize.
Inoltre controllare anche l'attributo memory_limit che non 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 ha l'accesso di scrittura nella directory specificata.
I permessi nei server *nix riguardano chi può leggere e scrivere nelle directories e nei files e sono divisi in tre gruppi: proprietario, gruppo, altro.
I permessi possono essere regolati dalla maggior parte dei programmi FTP.
Per le directories dove i file devono essere scritti, i permessi 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", "Safe Mode Restriction in effect" oppure "la funzione è stata disabilitata per motivi di sicurezza".
Questo tipo di errore è comune a quegli script che lavorano su web hosting providers condivisi e indica che PHP sta lavorando in modo protetto (Safe Mode).
Il modo protetto permette agli amministratori di sistema di controllare quali utenti sono abilitati e quali funzioni disabilitare per motivi di sicurezza.
Senza l'accesso al file PHP.ini, il modo protetto può essere disattivato dall'amministratore di sistema.

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

1. Nella versione PHP 4.2.0 è stato introdotto un nuovo elemento nella stringa $HTTP_POST_FILES che restituisce uno specifico messaggio di errore se l'upload del file fallisce. Viene utilizzato in questo modo:
$HTTP_POST_FILES['file']['error']
e restituisce quanto segue:
0: nessun errore, il file è stato caricato con successo
1: l'upload del file ha una dimensione maggiore rispetto a quanto indicato nella stringa upload_max_filesize del php.ini
2: l'upload del file ha una dimensione maggiore rispetto a quanto indicato nella stringa max_file_size del codice HTML
3: Il file è stato caricato solo parzialmente
4: Nessun file è stato caricato
Questi messaggi sono particolarmente utili per il controllo degli errori e per determinare il successo o il fallimento del caricamento di un file, ma siccome sono solo supportate dalle nuove versioni di PHP, non potete fare affidamento sulla loro esistenza se programmate script per la distribuzione.

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

3. is_uploaded_file() non è disponibile in tutte le versione di PHP: se siete così sfortunati da usare una particolare versione di PHP che non supporta questa funzione, potete controllare se un file è stato caricato oppure no, 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 di convalida dal lato server, potete specificare la dimensione massima usando un campo nascosto dentro il form in questo modo:

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

INFINE

In questo articolo avete avuto un assaggio di come lavorare con l'upload dei files.
Le cose da ricordare sono:
* Quando create un form che include il campo "file upload", dovete includere nel tag: enctype="multipart/form-data" così da dire al browser che c'è un upload e settare il metodo del form su POST
* In molte configurazioni, il file caricato sarà disponibile in una stringa $http_post_vars con lo stesso nome del file assegnato nel campo "file upload"
* Quando accettate l'upload di files, generalmente dovete fare 3 controlli: se il file è stato caricato oppure no; la dimensione del file caricato; il tipo di file caricato
* Il file temporaneo deve essere cancellato con la funzione unlink() dopo che il file è stato copiato nella destinazione finale oppure se l'upload del file fallisce uno dei 3 controlli sopra elencati.