Fisiere stocate in baza de date cu PHP si MySQL

Share on:

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:

1CREATE TABLE IF NOT EXISTS fisiere (
2  ID int(10) unsigned NOT NULL AUTO_INCREMENT,
3  nume varchar(255) NOT NULL,
4  tip varchar(255) NOT NULL,
5  marime int(11) NOT NULL,
6  fisiere longblob NOT NULL,
7  timp int(11) DEFAULT NULL,
8  PRIMARY KEY (`ID`)
9) ENGINE=MyISAM

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

Conectarea la baza de date:

1<?php
2// db.php
3mysql_connect('localhost', 'user', 'parola');
4mysql_select_db('fisiere');
5
6// am omis intentionat tag-ul de inchis pt PHP
7// 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

  1<?php
  2// legatura la baza de date
  3include('db.php');
  4
  5// mesaj de eroare
  6$errmsg = NULL;
  7
  8// stergerea fisierului din BD
  9if(isset($_GET['del']))
 10{
 11    $qr="DELETE FROM fisiere WHERE ID='".mysql_escape_string($_GET['del'])."'";
 12    if(!mysql_query($qr)) {
 13       $errmsg = 'Fisierul nu a putut fi sters!<br>';
 14    }
 15}
 16
 17// verificam daca a fost trimis un fisier si are diminesiunea mai mare de 0
 18if($_FILES['fisier']['size'] > 0) {
 19
 20   // se citeste continutul fisierului
 21   $content = file_get_contents($_FILES['fisier']['tmp_name']);
 22
 23   // se codeaza cu base64_encode pt a nu aparea probleme la caractere speciale
 24   //si se sparge in bucati
 25   $content = chunk_split(base64_encode($content));
 26
 27   // se introduc datele in baza de date
 28   $qr="INSERT INTO fisiere SET
 29      nume   ='".mysql_escape_string($_FILES['fisier']['name'])."',
 30      tip    ='".mysql_escape_string($_FILES['fisier']['type'])."',
 31      marime ='".mysql_escape_string($_FILES['fisier']['size'])."',
 32      fisiere='".$content."',
 33      timp   ='".time()."'";
 34
 35   // se verifica daca datele au fost inserate cu succes
 36   if(mysql_query($qr)) {
 37      // daca datele au fost stocare cu succes se face refres la pagina
 38      // pentru a evita cazul in care utilizatorul apasa "refresh"
 39      header("Location: ".$PHP_SELF."?ok=1");
 40      exit();
 41   } else {
 42      $errmsg = 'Eroare la upload<br>';
 43   }
 44
 45}
 46?>
 47<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 48"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 49<html xmlns="http://www.w3.org/1999/xhtml">
 50<head>
 51<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 52<title>Fisiere</title>
 53</head>
 54
 55<body>
 56<?php
 57if($_GET['ok']==1) echo "fisierul a fost incarcat!";
 58// afisaza mesajul de eroare daca acesta exista
 59if($errmsg) echo $errmsg;
 60?>
 61
 62<?php
 63// selecteaza fisierele din BD
 64$qr="SELECT * FROM fisiere ORDER BY timp";
 65$rez=mysql_query($qr);
 66if(mysql_num_rows($rez)>0) {
 67?>
 68<table border="1">
 69   <tr>
 70      <td>ID</td>
 71      <td>Nume</td>
 72      <td>Ora</td>
 73      <td>Descarca</td>
 74      <td>sterge</td>
 75   </tr>
 76   <?php
 77   while($row=mysql_fetch_array($rez)) {
 78   ?>
 79   <tr>
 80      <td><?php echo $row["ID"]; ?></td>
 81      <td><?php echo $row["nume"]; ?></td>
 82      <td><?php echo date("d-m-Y",$row["timp"]); ?></td>
 83      <td><a href="descarca.php?ID=<?php echo $row["ID"]; ?>">descarca fisier</a></td>
 84      <td>
 85        <a href="<?php echo $_SERVER['PHP_SELF']; ?>?del=<?php echo $row["ID"] ?>"
 86            onclick="return confirm('doriti sa stergeti acest fisier?');">
 87          sterge
 88        </a>
 89      </td>
 90    </tr>
 91    <?php } ?>
 92</table>
 93<?php
 94} else {
 95    echo "nu exista fisiere in baza de date!";
 96}
 97?>
 98<br />
 99<br />
100<form method="post" enctype="multipart/form-data"
101   action="<?php echo $_SERVER['PHP_SELF']; ?>">
102<input type="file" name="fisier" />
103<input type="submit" value="Incarca" />
104</form>
105</body>
106</html>

Descarcarea fisierului:

 1<?php
 2include('db.php');
 3
 4// selectarea fisierului din BD
 5$qr="SELECT * FROM fisiere WHERE ID='".mysql_escape_string($_GET['ID'])."'";
 6$rez=mysql_query($qr);
 7$row=mysql_fetch_array($rez);
 8
 9$size = $row['marime'];
10$type = $row['tip'];
11$name = $row['nume'];
12$fisiere = $row['fisiere'];
13
14// dezactivam compresia pt ca nu aparea erori la afisare
15if(ini_get('zlib.output_compression'))
16ini_set('zlib.output_compression', 'Off');
17
18// fisierul trebuie descarcat de pe server nu din cache
19header("Pragma: public");
20header("Expires: 0");
21header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
22header("Cache-Control: private",false); 
23
24// dimensiunea fisierului
25header("Content-length: ".$size);
26
27// tipul fisierului
28header("Content-Type: ".$type); 
29
30// optional daca dorim sa forteze download-ul
31header("Content-Type: application/force-download");
32
33// numele fisierului cu care va fi salvat pe disk
34header("Content-Disposition: attachment; filename=\"".$name."\";"); 
35
36// transfer binar pt a evita caracterele speciale
37header("Content-Transfer-Encoding: binary");
38
39// decodam continutul fisierului si il afisam
40echo base64_decode($fisiere);
41
42?>

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.