Come gestire i file: le basi (Parte 1)
“Bene, non mi resta altro da fare che caricare questa nuova copertina e la galleria fotografica sarà pronta!… Ma… come è possibile che il file esiste già? Lo elimino và… Impossibile leggerlo? Ma è lì dai, come fa a non leggerlo?!”
Non ti è mai capitata una situazione del genere?
Sei pronto a creare la tua galleria fotografica, il tuo pacchetto di file… ed ecco che spuntano fuori errori su errori, il file esiste già, non riesci né ad eliminarlo né tantomeno a leggerlo.
A tal proposito, ho creato una guida di quattro articoli per aiutarti a risolvere questi problemi.
Struttura della guida
Come gestire i file: le basi (parte 1)
Questo primo articolo è incentrato sulla creazione di una classe per gestire i file. Ti mostro come effettuare controlli di sicurezza preliminari e alcuni metodi per ottenere informazioni basilari.
Come gestire i file: le basi (parte 2)
Ecco come cercare, leggere ed eliminare i file, effettuando controlli a monte ed eliminando ogni futuro e possibile problema.
Come gestire i file: il download
Vediamo come effettuare il download dei file in sicurezza per te e per i tuoi utenti.
Come gestire i file: l’upload
Ed infine ecco come effettuare l’upload dei file sul server, con l’ausilio della classe class.upload.
Pochi metodi e molta efficacia
Io sono un amante della programmazione ad oggetti ed ho pensato di scrivermi una classe per poter fare tutto ciò per il quale prima scrivevo righe e righe di codice ogni volta. Ovviamente la classe da sola ha poca utilità, bisognerà integrarla in un sistema già esistente. Ma basta chiacchiere, tuffiamoci nel PHP ed iniziamo a scrivere la base per far funzionare la nostra classe.
/** * Classe per velocizzare i controlli e la gestione dei file. */ class YCFile { //Controlla l’esistenza del file ed eventualmente restituisce informazioni con pathinfo(). public static function exists($file, $getInfo = false) { } //Controlla che il file sia leggibile o meno public static function isReadable($file) { } //Restituisce l’estensione del file public static function ext($file) { } //Restituisce il nome del file senza estensione public static function name($file) { } //Restituisce il nome del file comprensivo di estensione public static function realName($file) { } //Elimina caratteri non consentiti dal nome del file public static function sanitizeName($file) { } //Cerca un file e, in caso positivo, restituisce il suo percorso public static function find($file, $base) { } //Genera un array contenente i file trovati nella cartella indicata public static function listFile($dir, $ext = false) { } //Elimina un file public static function delete($file) { } //Legge il contenuto di un file public static function read($file, $totalChunk = 0, $chunkSize = 8192, $offset = 0) { } }
Bene, abbiamo ora uno scheletro della classe.
Come vedi i metodi sono pochi e dai loro nomi è molto semplice intuirne lo scopo.
Passiamo all’analisi e la stesura di ogni metodo.
Come prima cosa per poter lavorare con un file, dobbiamo essere sicuri che esista, altrimenti su cosa lavoriamo?
/* … */ class YCFile { //Controlla l’esistenza del file ed eventualmente restituisce informazioni con pathinfo(). public static function exists($file, $getInfo = false) { //Controlliamo che il file esista e che sia veramente un file if(is_file($file)) { //Se vogliamo, ci facciamo restituire informazioni come l’estensione, il nome ecc... if($getInfo) { return pathinfo($file); } return true; } return false; } //Controlla che il file sia leggibile o meno public static function isReadable($file) { return (self::exists($file) AND is_readable($file)); } /* … */ }
Nel metodo YCFile::exists() ho aggiunto la funzione pathinfo() per comodità. Potresti voler utilizzare un solo metodo per avere tutto subito sottomano. Io solitamente uso questo metodo solo per controllare che il file esista poiché pathinfo() restituisce un array di informazioni e non ho mai voglia di riordinare questo array in altre variabili con un nome adatto (si, sono un maniaco della precisione).
Con il metodo YCFile::isReadable() puoi controllare anche che il file sia leggibile.
Vedremo la sua utilità nel metodo YCFile::read().
Iniziamo a lavorare al file
Ora che sei sicuro che il tuo file esista e sia realmente leggibile, puoi iniziare a lavorarci.
Sicuramente avrai bisogno di sapere il suo nome e la sua estensione.
Quindi scriviamo i metodi YCFile::name(), YCFile::ext(), YCFile::realName() e YCFile::sanitizeName().
/* … */ class YCFile { /* … */ //Restituisce l’estensione del file public static function ext($file) { return substr($file, strrpos($file, '.') + 1); } //Restituisce il nome del file senza estensione public static function name($file) { //Se non sono in ambiente Unix, sostituisco il separatore con il carattere slash ( / ) if(DIRECTORY_SEPARATOR != '/') { $file = str_replace(DIRECTORY_SEPARATOR, '/', $file); } $lastSlash = strrpos($file, '/'); //Il parametro $file è una path, quindi estraggo solo il nome del file. if($lastSlash) { $file = substr($file, $lastSlash + 1); } return substr($file, 0, strrpos($file, '.')); } //Restituisce il nome del file comprensivo di estensione public static function realName($file) { return self::name($file) . '.' . self::ext($file); } //Elimina caratteri non consentiti dal nome del file public static function sanitizeName($file) { $fileName = preg_replace('/[^\w\.\-]/', '_', self::realName($file)); return dirname($file) . DIRECTORY_SEPARATOR . $fileName; } /* … */ }
Come vedi anche il funzionamento di questi quattro metodi è estremamente semplice.
YCFile::ext() non fa altro che cercare l’ultimo punto nel parametro passato ed estrarre la porzione di stringa da quella posizione fino alla fine.
YCFile::name() cerca l’ultimo slash estraendo quindi solo il nome del file. Per uniformare il metodo su tutti i sistemi, ho preferito sostituire qualunque divisore con lo slash.
YCFile::realName() è una scorciatoria per invocare entrambi i metodi contemporaneamente.
YCFile::sanitizeName() invece pulisce il nome del file sostituendo tutto ciò che non sia un numero, una lettera, un punto o un trattino con un underscore. Come sicuramente sai potrebbero causare dei problemi gli spazi nel nome del file, ma io preferisco eliminare anche altri caratteri speciali. Con questo metodo risolveremo ogni problema ancor prima che si possa presentare.
Ecco tutto il codice scritto fin ora:
/** * Classe per velocizzare i controlli e la gestione dei file. */ class YCFile { //Controlla l’esistenza del file ed eventualmente restituisce informazioni con pathinfo(). public static function exists($file, $getInfo = false) { //Controlliamo che il file esista e che sia veramente un file if(is_file($file)) { //Se vogliamo, ci facciamo restituire informazioni come l’estensione, il nome ecc... if($getInfo) { return pathinfo($file); } return true; } return false; } //Controlla che il file sia leggibile o meno public static function isReadable($file) { return (self::exists($file) AND is_readable($file)); } //Restituisce l’estensione del file public static function ext($file) { return substr($file, strrpos($file, '.') + 1); } //Restituisce il nome del file senza estensione public static function name($file) { //Se non sono in ambiente Unix, sostituisco il separatore con il carattere slash ( / ) if(DIRECTORY_SEPARATOR != '/') { $file = str_replace(DIRECTORY_SEPARATOR, '/', $file); } $lastSlash = strrpos($file, '/'); //Il parametro $file è una path, quindi estraggo solo il nome del file. if($lastSlash) { $file = substr($file, $lastSlash + 1); } return substr($file, 0, strrpos($file, '.')); } //Restituisce il nome del file comprensivo di estensione public static function realName($file) { return self::name($file) . '.' . self::ext($file); } //Elimina caratteri non consentiti dal nome del file public static function sanitizeName($file) { $fileName = preg_replace('/[^\w\.\-]/', '_', self::realName($file)); return dirname($file) . DIRECTORY_SEPARATOR . $fileName; } //Cerca un file e, in caso positivo, restituisce il suo percorso public static function find($file, $base) { } //Genera un array contenente i file trovati nella cartella indicata public static function listFile($dir, $ext = false) { } //Elimina un file public static function delete($file) { } //Legge il contenuto di un file public static function read($file, $totalChunk = 0, $chunkSize = 8192, $offset = 0) { } }
Conclusioni
Come vedi questi primi metodi sono semplici, ma fanno il loro sporco lavoro.
Nella prossima parte dell’articolo ti mostrerò come trovare un file, come leggerlo evitando di scrivere ogni volta almeno 20 righe di codice e come cancellarlo senza far spuntare i fatidici Warning e Fatal Error.
Questo è il mio metodo preferito per lavorare con i file. E tu invece come procedi? Usi una classe, ne hai scritta anche tu una o usi le funzioni di PHP senza tanti fronzoli di OOP?
Secondo te ho usato un giusto metodo per pulire il nome del file o pensi che sia eccessivo?
57 commenti
Trackback e pingback
[...] precedente articolo abbiamo potuto vedere come gestire le informazioni necessarie a lavorare con un [...]
[...] articoli precedenti (Come gestire i file: le basi parte 1 e parte 2) abbiamo visto come creare la classe…
[...] Come gestire i file: le basi (parte 1) Questo primo articolo è incentrato sulla creazione di una classe per…