Thursday, March 21, 2013

CodeIgniter-Bonfire and Images

Here is simple code for displaying images in an MVC framework like CodeIgniter-Bonfire. This entry assumes that one already has an understanding of how such a framework works.

The Database Table

Ideally, your database table would contain the following columns with the following types: id (int(11)), title (varchar(255)), mimetype (varchar(255)), filesize (int(11)), content (longblob).

The id, title, and filesize columns are self-explanatory. The mimetype is information you need later on for rendering the photo and can be obtained as you're uploading the photo. (The filesize is also something you can get when you're uploading the photo.) The content is the image itself in a binary format.

The View

At the very least, the view will have a form with one input element of type file so that you can upload the photo. Once you submit the form, you can validate the file size and the extension.

Sample form:

< form action="http://some.website.com/images/create" enctype="multipart/form-data"> < /form>

< input id="file" name="file" type="file" />

< input name="save" type="submit" value="Upload" />


The enctype must be 'multipart/form-data.' Otherwise, the $_FILES variable will not be created when you submit the form. $_FILES will contain all the file information you need. If the input box is named 'file', you can get the uploaded file's size through $_FILES['file']['size'].

Sample controller:
class images extends Front_Controller
{
  public function create()
  {
    if ($_FILES['file']['size'] > 0)
    {
      // Get the file info
      $name = $_FILES['file']['name'];
      $size = $_FILES['file']['size'];
      $type = $_FILES['file']['type'];
      $tmpname = $_FILES['file']['tmp_name'];
      
      // Grab the contents of the photo
      $fp = fopen($tmpname, 'r');
      $content = fread($fp, filesize($tmpname));
      fclose($fp);

      // Load your model, if your constructor doesn't 
      //do it for you
      $this->load->model('images/Images_model', 
      'images_model');

      $data['title']        = $name;
      $data['mimetype']     = $type;
      $data['filesize']     = $size;
      $data['content']      = $content;

      // Save the image
      $insert_id = $this->images_model->insert($data);

      // Now go print out a success message if $insert_id 
      // is an integer,or an error message if it's false
    }
  }
}

Displaying the image 
 
When you want to display the image, the img tag's src should point to another function in your images controller. This function retrieves the images' content from the databases and prints it out with the appropriate headers.

Sample view

Here is a photo: 
< img src="http://some.website.com/images/fetch/8" alt='a picture' />

The controller function will look like the following (put this below the create() function):
public function fetch($id)
{
  $this->load->model('images/Images_model', 
  'images_model');
  $image = $this->images_model->find($id);
  ob_clean();
  header("Content-type: ".$image->mimetype);
  echo $photo->content;
}

And that's it! The image will be echoed out to the browser as an actual image (as opposed to the garbage it looks like in the database) because of the Content-type. Your browser knows how to interpret the following data.