Location: PHPKode > scripts > FileDB > filedb/FileDB.php
<?php
////////////////////////////////////////////////////////////////////////
/*

Class for storing (binary) files in a database.

For the lastest version go to:
http://www.phpclasses.org/browse.html/package/930.html

With this class you can easily store, display and send files from a db. 
It has an build in hit counter and stores information of last editing, upload, etc.


This class uses my db abstraction layer, AbstractDB
(http://www.phpclasses.org/browse.html/package/846.html) , which allows a unified
and easy access to databases, which you can see in this class. 


CONSTRUCTOR:
    function FileDB(&$db, $host, $database, $user, $password)

FUNCTIONS:
    function add($file_name, $file_descr = '')
    function remove($id)
    function get($id, $addHit = true)
    function getWhere($from, $where = '', $addHit = true)
    function getFile($id, $addHit = true)
    function getFileData($id)
    function getIds()
    function sendFile($id, $contentType)

    function _getFileContent($file_name)
    
PUBLIC VARS:
    var $file_count
    
////////////////////////////////////////////////////////////////////////

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
    
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
    
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
////////////////////////////////////////////////////////////////////////
/**
* Class for handling bin data in a database
*
* @author	    Lennart Groetzbach <hide@address.com>
* @copyright	Lennart Groetzbach <hide@address.com> - distributed under the LGPL
* @version 	    0.52 BETA - 2003/01/17
<p>
History / Changes<br>
<table border="1" width="100%" cellpadding="3"><tr>
      <th>Version</th>    <th>Reported By</th>        <th>File / Function Changed</th>    <th>Date of Change</th> <th>Commment</th>
</tr><tr>
      <td>0.51</td>        <td>Matthias Haldimann</td>        <td>sendFile()</td>            <td>2002/12/15</td>     <td>added parameter for content type</td>
</tr><tr>
      <td>0.52</td>        <td>-</td>        <td>sendFile()</td>            <td>2002/01/17</td>     <td>made download compatible for most browser</td>
</tr>
</table>

*/
class FileDB {

////////////////////////////////////////////////////////////////////////

/**
* db abstraction layer
* 
* @access   private
* @type     Object  AbstractDB
*/
var $_db = null;
/**
* number of files in db
* 
* @access   public
* @type     Integer
*/
var $file_count = -1;

////////////////////////////////////////////////////////////////////////
/**
* Constructor
*
* Opens the connection to the db
* 
* @access   public
*
* @param    Object      &$db
* @param    String      $host
* @param    String      $database
* @param    String      $user
* @param    String      $password
*/
function FileDB(&$db, $host, $database, $user, $password) {
    if ($db && $host && $db) {
        $this->_db = $db;
        if ($this->_db->connect($host, $database, $user, $password)) {
            $this->_db->query('select count(*) from files');
            $this->file_count = $this->_db->getValue();
        } else {
            die ('Error connecting to db!');
        }
    } else {
        if (!$db) {
            die('DB Layer is not set!');
        } else if (!$host) {
            die ('Host is not set!');
        } else {
            die ('Database is not set!');
        }
    }
}

////////////////////////////////////////////////////////////////////////
/**
* Adds file to the db
*
* Adds file to the db and increases the file count
* 
* @access   public
*
* @param    String      $file_name
* @param    String      $file_descr
* 
* @return   boolean     TRUE if successful
*/

function add($file_name, $file_descr = '') {
    $data = $this->_getFileContent($file_name);
    if ($data != false) {
        $size = filesize($file_name);
        $str = "INSERT INTO files (file_name, file_size, bin_data, descr, added, last_visited, last_edited) VALUES (\"%s\", \"%s\", \"%s\", \"%s\", %s, %s, %s)";
        $query = sprintf($str, strtolower(basename($file_name)), $size, $data, addslashes(strip_tags($file_descr)), 'now()', 'now()', 'now()');
        if ($this->_db->query($query)) {
            $this->file_count++;
            return true;
        }
    }
    return false;
}
 
////////////////////////////////////////////////////////////////////////
/**
* Edits file data
*
* Edits an entry in the db
* 
* @access   public
*
* @param    Array      $array
* array(
*        "id"               => the identifier *
*        "file_name"        => name of the file
*        "file_descr"       => description of the file
*        "bin_data"         => file data
*        "hits"             => number of downloads
*   )
*   (*) is mandatory
*
* @return   boolean     TRUE if successful
*/

function edit($array) {
    if (is_array($array)) {
        $new = $array;
        $old = $this->get(@$array['id'], false);
        // the entry exists
        if ($old) {
            // calculate the size
            if (array_key_exists('bin_data', $new)) {
                $new['size'] = strlen($new['bin_data']);            
            }
            $str = '';
            // update the time
            $str .= 'last_edited=now(), ';
            foreach($new as $key => $value) {
                // remove all invalid keys
                if (!array_key_exists($key, $old)) {
                    unset($new[$key]);
                //
                } else {
                    switch ($key) {
                        // don't allow to change the internal time data
                        case "added":
                        case "last_edited":
                        case "last_visited":
                        // nor the id or size
                        case "id":
                        case "size":
                            break;
                        case "descr":
                            $str .= "$key=\"" . addslashes(strip_tags($value)) . "\", ";
                            break;
                        default:
                            $str .= "$key=\"" . addslashes($value) . "\", ";
                            break;
                    }
                }
            }
            // send the query
            $query = "update files set " . substr($str,0 , -2) . " where id=" . $new['id'];
            if ($this->_db->query($query)) {
                return true;
            }
        }
    }
    return false;
}

////////////////////////////////////////////////////////////////////////
/**
* Removes file to the db
*
* Removes file and decreass file count
* 
* @access   public
*
* @param    Integer     $id
* 
* @return   boolean     TRUE if successful
*/
function remove($id) {
    if ($id) {
        $this->_db->query("select id from files where id=\"$id\"");
        if ($this->_db->getValue() != false) {
            if ($this->_db->query("delete from files where id=\"$id\" limit 1")) {
                $this->file_count--;
                return true;
            }
        }
    } 
    return false;
}

////////////////////////////////////////////////////////////////////////
/**
* Creates user download dialog  
*
* Sends the file to the user, should be called in an empty page
* 
* @access   public
*
* @param    Integer     $id
* @param    String      $contentType
* 
* @return   boolean     FALSE on error
*/

function sendFile($id, $contentType = 'application/save') {
    if ($id) {
        $data = $this->getWhere('bin_data, file_name, file_size', "id=$id");
        if ($data) {
            $bin = $data[0]['bin_data'];
            header('Content-Type: ' . $contentType);
            header('Content-Length: ' . $data[0]['file_size']);
            header('Content-Disposition: attachment; filename=' . trim($data[0]['file_name']));
            header("Content-Transfer-Encoding: binary");
            echo $bin;
            exit();
        }
    }
    return false;
}
    
////////////////////////////////////////////////////////////////////////
/**
* Returns the full file information
*
* Returns the full file information
* 
* @access   public
*
* @param    Integer     $id
* @param    boolean     $addHit
* 
* @return   mixed       an Array or FALSE if an error occurs
*/
function get($id, $addHit = true) {
    if ($id) {
        $this->_db->query("select * from files where id=\"$id\"");
        $data = $this->_db->getNext(ASSOCIATIVE_ARRAY);
        if ($data) {
            if ($addHit == true) {
                $this->_db->query("update files set hits=hits+1, last_visited=now() where id=\"$id\"");
            }
            return $data;    
        }
    }
    return false;
}

////////////////////////////////////////////////////////////////////////
/**
* Returns specified file information 
*
* Free definable select and where clauses for file information
* 
* @access   public
*
* @param    String      $select
* @param    String      $where
* @param    boolean     $addHit
* 
* @return   mixed       an Array or FALSE if an error occurs
*/
function getWhere($select, $where = '', $addHit = true) {
    if ($select != '') {
        $where_clause = ($where == '' ? '' : "where $where");
        $this->_db->query("select $select from files $where_clause");
        $data = $this->_db->getAll(ASSOCIATIVE_ARRAY);
        if ($data) {
            if ($addHit == true) {
                $this->_db->query("update files set hits=hits+1, last_visited=now() $where_clause");
            }
            return $data;    
        }
    }
    return false;
}

////////////////////////////////////////////////////////////////////////
/**
* Returns the binary file data
*
* Returns the binary file data 
* 
* @access   public
*
* @param    Integer     $id
* @param    boolean     $addHit
* 
* @return   mixed       a String or FALSE if an error occurs
*/

function getFile($id, $addHit = true) {
    if ($id) {
        $this->_db->query("select bin_data from files where id=\"$id\"");
        $data = $this->_db->getValue();
        if ($data) {
            if ($addHit == true) {
                $this->_db->query("update files set hits=hits+1, last_visited=now() where id=\"$id\"");
            }
            return $data;    
        }
    }
    return false;
}

////////////////////////////////////////////////////////////////////////
/**
* Returns the file information
*
* Returns the file information without the binary data
* 
* @access   public
*
* @param    Integer     $id
* 
* @return   mixed       a String or FALSE if an error occurs
*/

function getFileData($id) {
    if ($id) {
        $this->_db->query("select id, descr, file_name, file_size, hits from files where id=\"$id\"");
        $data = $this->_db->getNext(ASSOCIATIVE_ARRAY);
        if ($data) {
            return $data;    
        }
    }
    return false;
}


////////////////////////////////////////////////////////////////////////
/**
* Returns all file ids
*
* Returns an array with all file ids 
* 
* @access   public
* 
* @return   mixed       an Array or FALSE if an error occurs
*/
function getIds() {
    $this->_db->query("select id from files");
    return $this->_db->getColumn(ASSOCIATIVE_ARRAY);
}

////////////////////////////////////////////////////////////////////////
/**
* Returns the content of a file
*
* Returns binary data
* 
* @access   private
*   
* @param    String     $file_name
* 
* @return   mixed       a String or FALSE if an error occurs
*/
function _getFileContent($file_name) {
    if (file_exists($file_name)) {
        $size = filesize($file_name);
        $fp = @fopen($file_name, 'rb');
        if ($fp) {
            $data = fread($fp, $size);
            fclose($fp);
            return addslashes($data);
        }    
    }
    return false;
}
////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////
// PHP function for older versions
////////////////////////////////////////////////////////////////////////
// (PHP 4 >= 4.1.0)
if (!function_exists('array_key_exists')) {
/**
* Does a given key exists
* For php versions < 4.1
* 
* @access   private
* @param    String      $key
* @param    Array       $array
* @return   Boolean
*/    function array_key_exists($key, $array) {
        foreach(@$array as $current_key => $val) {
            if ($current_key === $key) {
                return true;
            }
        }
        return false;
    }
}
////////////////////////////////////////////////////////////////////////
?>
Return current item: FileDB