Saving files to a blob field in the database

As a follow-up from the How to upload a file using a model wiki entry that explains how to save a file to the filesystem, this article will do the same using a blob field in the database.

Edit the model:

The first step is to change the model in order to self manage the file:

class Candidate extends CActiveRecord
{
	/**
 	 * Property for receiving the file from the form
	 * It should be different from any other field in the database
	 */
	public $uploadedFile;

	public function rules()
	{
		return array(
			array('uploadedFile', 'file', 'types'=>'jpg, gif, png'),
		);
	}


	/**
	* Saves the name, size, type and data of the uploaded file
	*/
	public function beforeSave()
	{
		if($file=CUploadedFile::getInstance($this,'uploadedFile'))
		{
			$this->file_name=$file->name;
			$this->file_type=$file->type;
			$this->file_size=$file->size;
			$this->file_content=file_get_contents($file->tempName);
		}

	return parent::beforeSave();
	}
}

Do not forget to give a rule for this attribute as it has to be safe. Is also a good practice to delete any rule referring to the other 4 fields (file_name, file_type, file_size, file_content), as they are not supposed to be modified by massively assigned inputs.

Edit the view:

In the view we can put:

<div class="row">
<?php echo $form->labelEx($model,'uploadedFile'); ?>
<?php echo $form->fileField($model,'uploadedFile'); ?>
<?php echo $form->error($model,'uploadedFile'); ?>
</div> 
Displaying images:

In the view we put the code:

<? echo CHtml::link(my_link_name,array('displaySavedImage','id'=>$model->primaryKey)); ?>

So it generates link like http://myserver/yii/myapp/index.php?r=candidate/displaySavedImage&id=1

Where Candidate is current model.

To show saved image we can write an action in Controller:

/**
 * Opens the dialog in browser to open/save the image.
 */
public function actionDisplaySavedImage()
{
	$model=$this->loadModel($_GET['id']);

	header('Pragma: public');
	header('Expires: 0');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Content-Transfer-Encoding: binary');
	header('Content-length: '.$model->file_size);
	header('Content-Type: '.$model->file_type);
	header('Content-Disposition: attachment; filename='.$model->file_name);

        echo $model->file_content;
}

Note $_GET['id'] as passed argument of loadModel function.

6 2
17 followers
Viewed: 79 366 times
Version: 1.1
Category: Tips
Written by: zaccaria
Last updated by: zaccaria
Created on: Nov 3, 2010
Last updated: 13 years ago
Update Article

Revisions

View all history

Related Articles