Claudiu Persoiu

Blog-ul lui Claudiu Persoiu


Fisiere stocate in baza de date cu PHP si MySQL

without comments

In continuare voi prezenta un mic tutorial despre stocarea fisierelor in baza de date.

Cand avem nevoie de stocarea fisierelor in baza de date? Un scenariu bun este atunci cand fisierele sunt confidentiale.

Dezavantajul principal este viteza de acces, cat timp mai este si o baza de date la mijloc asta va intarzia procesul de regasire/afisare.

Structura bazei de date:

CREATE TABLE IF NOT EXISTS fisiere (
  ID int(10) unsigned NOT NULL AUTO_INCREMENT,
  nume varchar(255) NOT NULL,
  tip varchar(255) NOT NULL,
  marime int(11) NOT NULL,
  fisiere longblob NOT NULL,
  timp int(11) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=MyISAM

Trebuie sa stocam tipul, marimea si continutul fisierului propriuzis. Numele este retinut mai mult pt extensie.

Conectarea la baza de date:

<?php
// db.php
mysql_connect('localhost', 'user', 'parola');
mysql_select_db('fisiere');

// am omis intentionat tag-ul de inchis pt PHP
// ca sa am certitudinea ca nu se trimit headere

Fisierul de upload si listare:

In acest fisier se afla adaugare, stergerea si listarea fisierelor din baza de date

<?php
// legatura la baza de date
include('db.php');

// mesaj de eroare
$errmsg = NULL;

// stergerea fisierului din BD
if(isset($_GET['del']))
{
    $qr="DELETE FROM fisiere WHERE ID='".mysql_escape_string($_GET['del'])."'";
    if(!mysql_query($qr)) {
       $errmsg = 'Fisierul nu a putut fi sters!<br>';
    }
}

// verificam daca a fost trimis un fisier si are diminesiunea mai mare de 0
if($_FILES['fisier']['size'] > 0) {

   // se citeste continutul fisierului
   $content = file_get_contents($_FILES['fisier']['tmp_name']);

   // se codeaza cu base64_encode pt a nu aparea probleme la caractere speciale
   //si se sparge in bucati
   $content = chunk_split(base64_encode($content));

   // se introduc datele in baza de date
   $qr="INSERT INTO fisiere SET
      nume   ='".mysql_escape_string($_FILES['fisier']['name'])."',
      tip    ='".mysql_escape_string($_FILES['fisier']['type'])."',
      marime ='".mysql_escape_string($_FILES['fisier']['size'])."',
      fisiere='".$content."',
      timp   ='".time()."'";

   // se verifica daca datele au fost inserate cu succes
   if(mysql_query($qr)) {
      // daca datele au fost stocare cu succes se face refres la pagina
      // pentru a evita cazul in care utilizatorul apasa "refresh"
      header("Location: ".$PHP_SELF."?ok=1");
      exit();
   } else {
      $errmsg = 'Eroare la upload<br>';
   }

}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Fisiere</title>
</head>

<body>
<?php
if($_GET['ok']==1) echo "fisierul a fost incarcat!";
// afisaza mesajul de eroare daca acesta exista
if($errmsg) echo $errmsg;
?>

<?php
// selecteaza fisierele din BD
$qr="SELECT * FROM fisiere ORDER BY timp";
$rez=mysql_query($qr);
if(mysql_num_rows($rez)>0) {
?>
<table border="1">
   <tr>
      <td>ID</td>
      <td>Nume</td>
      <td>Ora</td>
      <td>Descarca</td>
      <td>sterge</td>
   </tr>
   <?php
   while($row=mysql_fetch_array($rez)) {
   ?>
   <tr>
      <td><?php echo $row["ID"]; ?></td>
      <td><?php echo $row["nume"]; ?></td>
      <td><?php echo date("d-m-Y",$row["timp"]); ?></td>
      <td><a href="descarca.php?ID=<?php echo $row["ID"]; ?>">descarca fisier</a></td>
      <td>
        <a href="<?php echo $_SERVER['PHP_SELF']; ?>?del=<?php echo $row["ID"] ?>"
            onclick="return confirm('doriti sa stergeti acest fisier?');">
          sterge
        </a>
      </td>
    </tr>
    <?php } ?>
</table>
<?php
} else {
    echo "nu exista fisiere in baza de date!";
}
?>
<br />
<br />
<form method="post" enctype="multipart/form-data"
   action="<?php echo $_SERVER['PHP_SELF']; ?>">
<input type="file" name="fisier" />
<input type="submit" value="Incarca" />
</form>
</body>
</html>

Descarcarea fisierului:

<?php
include('db.php');

// selectarea fisierului din BD
$qr="SELECT * FROM fisiere WHERE ID='".mysql_escape_string($_GET['ID'])."'";
$rez=mysql_query($qr);
$row=mysql_fetch_array($rez);

$size = $row['marime'];
$type = $row['tip'];
$name = $row['nume'];
$fisiere = $row['fisiere'];

// dezactivam compresia pt ca nu aparea erori la afisare
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');

// fisierul trebuie descarcat de pe server nu din cache
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); 

// dimensiunea fisierului
header("Content-length: ".$size);

// tipul fisierului
header("Content-Type: ".$type); 

// optional daca dorim sa forteze download-ul
header("Content-Type: application/force-download");

// numele fisierului cu care va fi salvat pe disk
header("Content-Disposition: attachment; filename=\"".$name."\";"); 

// transfer binar pt a evita caracterele speciale
header("Content-Transfer-Encoding: binary");

// decodam continutul fisierului si il afisam
echo base64_decode($fisiere);

?>

Dupa cum se poate vedea serverul are destul de multe lucruri de facut pentru a afisa un simplu fisier, de asta nu este bine sa fie stocate pe disk toate fisierele, ar fi o risipa de resurse. Pe de alta parte,  fisierele private (cum ar fi cartile digitale sau melodiile) sunt clienti ideali pentru aceasta forma de stocare.

Written by Claudiu Persoiu

18 May 2009 at 4:00 PM

Posted in MySQL,PHP

Tagged with , , ,

Leave a Reply