Consulenze tecnologiche e informatiche
Upload di file in MySql

Upload di file in MySql

Capita di dover archiviare dei documenti all’interno del sito in modo da renderli accessibili attraverso dei link nelle pagine, ma nasce un problema di sicurezza se questi documenti devono essere visibili solo per persone che si sono autenticate sul sito e quindi riconosciute.

L’azione di protezione dagli accessi diretti può essere svolta in diversi modi: opportuna configurazione del web server; utilizzo di script di apertura che svincolano il documento dal link; protezione di tutta la porzione del sito attraverso le password del web server; etc.

Quello che andiamo ad illustrare è come salvare il documento all’interno di un campo del database, nello specifico Oracle mySql, in modo da focalizzare la sicurezza sul database e non dover gestire specifiche protezioni delle cartelle del sito.

Questa scelta ha come contro l’impatto in termini di prestazioni nelle query al database.

La mia scelta personale è quella di avere una tabella dedicata all’archiviazione dei documenti e quindi riportare nelle tabelle che usano il documento la sola chiave univoca del documento.

Creazione della tabella nel database Oracle mySql.

 

CREATE TABLE `doc_binary` (

  `iddoc` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `docbin` mediumblob NOT NULL,

  `docnome` varchar(32) NOT NULL,

  `docsize` varchar(50) NOT NULL,

  `doctype` varchar(50) NOT NULL,

  PRIMARY KEY (`iddoc`)

)

Definiamo la chiave primaria per la tabella (nell’esempio iddoc), che deve essere ad incremento automatico, personalmente la definisco come unsigned, in quanto come chiave non assumerà mai valori negativi. Inoltre non sapendo quale sarà la crescita dei contenuti nel corso del tempo preferisco utilizzare un formato INT(10), che in termini umani permette quasi una crescita infinita.

Con il campo docbin definiamo il contenitore del documento, nell’esempio utilizzo un formato MEDIUMBLOB, teniamo presente che i formati hanno circa le seguenti corrispondenze: BLOB = 65 Kbyte; MEDIUMBLOB = 16 Mbyte; LONGBLOB = 4 Gbyte.

Appare ovvio che il formato MEDIUMBLOB dovrebbe soddisfare tutte le esigenze.

Nel campo docnome andremo a scrivere il nome del documento, assegnare al campo una dimensione ragionevole per i nostri scopi. Possono essere usati i formati varchar o char.

Nei campi docsize e doctype verranno riportate rispettivamente la dimensione del documento e la sua codifica, ad esempio application/pdf nel caso di documenti pdf. Questi due campi saranno popolati direttamente dagli script di caricamento. Vista la variabilità della lunghezza delle stringhe suggerisco un formato varchar.

Creazioni degli script PHP

Per praticità divulgativa i passaggi sono spezzati in quattro distinti file: form di caricamento del file, script di caricamento del file, script di lista dei file e script di visualizzazione del file. Gli elementi possono essere integrati in diversi modi in base al proprio sito e migliorati con controlli e altre funzionalità.

Si presti attenzione al fatto che la dimensione massima dei file trasferibili verso un server attraverso degli script in PHP è determinato dalle opzioni di upload impostate nel file di configurazione php.ini, che determina il funzionamento del motore PHP. Quindi se il sito è in hosting tali valori possono variare tra i diversi provider.

Ai fine del nostro esempio la pagina form.php  si limita a queste poche righe.

<form method=”POST” action=”upload.php” ENCTYPE=”multipart/form-data”>

<input type=”hidden” name=”MAX_FILE_SIZE” value=”2000000″>

<input type=”submit” name=”carica” value=”Carica”>

</form>

Importante nella definizione del form è l’indicazione della stringa ENCTYPE=”multipart/form-data”, che rende possibile il passaggio dei file tra il browser e il server che ospita il sito e l’indicazione della dimensione massima di file accettati attraverso il parametro nascosto (type=”hidden”) MAX_FILE_SIZE, espresso in byte.

Il crescere delle dimensioni del file implica maggiori tempi per il suo trasferimento, con il rischio che entrino in gioco i timer di attesa del PHP, che implicano l’interruzione del trasferimento.

Fino a questo punto tutto avviene come per un comune trasferimento file, vediamo ora come lavora la componente upload.php che riceve il file.

  1. <?php
  2. if ($_FILES[‘file’][‘name’] == “” and $_FILES[‘file’][‘size’] == 0) exit;
  3. include (“db.inc.php”);
  4.  
  5. $file_name = $_FILES[‘file’][‘name’]
  6. $= $_FILES[‘file’][‘tmp_name’];
  7. $fileSize = $_FILES[‘file’][‘size’];
  8. $fileType = $_FILES[‘file’][‘type’];
  9.  
  10. $fp = fopen($tmpName, ‘r’);
  11. if ($fp) {
  12. $error = “OK”;
  13. $content = fread($fp, filesize($tmpName));
  14. $content = addslashes($content);
  15. fclose($fp);
  16.  
  17. if(!get_magic_quotes_gpc()) {
  18. $fileName = addslashes($fileName);
  19.  
  20. $query = “INSERT INTO doc_binary (docnome, docsize, doctype, docbin ) “;
  21. $query .= “VALUES (‘”.$file_name.”‘, ‘”.$fileSize.”‘, ‘”.$fileType.”‘, ‘”.$content.”‘)”;
  22.  
  23. mysql_query($query) or die($error = “KO”);
  24.  
  25. if ($error == “OK”) {
  26. ?>
  27. <font><b>Salvataggio completato.</b></font>
  28. <?php
  29. }
  30. else {
  31. ?>
  32. <font color=”red”><b>Salvataggio fallito.</b></font>
  33. <?php
  34. }
  35. }
  36. else {
  37. ?>
  38. <font color=”red”><b>Salvataggio fallito.</b></font>
  39. <?php
  40. }
  41. ?>

 

Riga 2

In ogni operazione di trasferimento dati è bene avere dei controlli sul trasferito e sull’accesso, in questo caso viene verificato che ci sia un nome file e che il file non sia vuoto.

Riga 4

Carichiamo quanto necessario per aprire l’accesso al database.

Riga 6-9

Assegniamo le informazioni ricevuto dal form, per quanto concerne il file, a delle variabili locali, nell’ordine abbiamo: nome file, nome del file temporaneo creato sul server, dimensione del file e tipo di file. In questo punto è possibile cambiare il nome del file rispetto a quello assegnato sul proprio pc, basta attribuire alla variabile $file_name il nome desiderato.

Riga 11

Apriamo il file temporaneo creato dal trasferimento.

Riga 12

Controlliamo se l’operazione di apertura del file è andata a buon fine, in caso contrario lo script salta alla riga 30 dando un messaggio di errore.

Riga 13

Forziamo una variabile di errore per indicare uno stato di OK, che useremo in seguito (riga 19).

Riga 14-16

Assegniamo il contenuto del file ad una variabile per quindi processarlo ed aggiungere degli slash prima dei caratteri speciali, che potrebbero creare problemi di salvataggio o di visualizzazione. Possiamo quindi chiudere il file.

Riga 18-20

Se non è impostata la gestione dei magic quote provvediamo ad eseguire la precedente operazione anche sul nome del file.

Riga 22-25

Prepariamo la query di inserimento ed inviamo i dati al database. In caso di errori nella scrittura facciamo in modo che l’operazione forzi la variabile di errore della riga 9 al valore KO.

Riga 27 – 37

Se la variabile della riga 9 è ancora nello stato di OK comunichiamo un esisto positivo in caso contrario negativo.

Lo scopo del caricamente di un file è quello di poterlo successivamente reperire, quindo procediamo alla visualizzazione di una lista dei file salvati, attraverso lo script list.php.

  1. <?php
  2. include (“db.inc.php”);
  3.  
  4. $query = “SELECT iddoc, docnome FROM doc_binary”;
  5.  
  6. $result = mysql_query($query) or die(mysql_error());
  7. while (list($id, $name) = mysql_fetch_array($result)) {
  8. ?>
  9. <a href=”read.php?id=”><?php echo $name; ?></a><br>
  10. <?php
  11. }
  12. ?>

Non ci dilinghiamo sulle spiegazioni di questo file, essendo di semplice realizzazione.

Passiamo ora all’apertura del documento, attraverso il file read.php, richiamato dal click sul link della pagina precedente.

  1. <?php
  2. include (“db.inc.php”);
  3. $id = $_GET[‘id’];
  4. $query = “SELECT docnome, doctype, docsize, docbin FROM doc_binary WHERE iddoc = ‘”.$id.”‘”;
  5. $result = mysql_query($query) or die(mysql_error());
  6. list($name, $type, $size, $content) = mysql_fetch_array($result);
  7. header(“Content-length: “.$size);
  8. header(“Content-type: “.$type);
  9. header(“Content-Disposition: attachment; filename=”.$name);
  10. echo $content;
  11. ?>

Riga 2

Carichiamo quanto necessario per aprire l’accesso al database.

Riga 4

Leggiamo l’id del documento passato dalla URL della lista file, questo parametro può essere letto e passato anche in altri modi.

Riga 5-6

Reperiamo nel database le informazioni relative al documento.

Riga 10-12

Inviamo al browser le informazioni per la visualizzazione del file.

Riga 13

Inviamo il documento in binario.

 

Categorie
Archivi
Count per Day
  • 2352Questo articolo:
  • 439242Totale letture:
  • 89Letture odierne:
  • 93Letture di ieri:
  • 21 Novembre 2016Dal: