Storing And Retrieving A File From Postgresql Bytea Column Type

I am a newbie in Yii Framework and PHP Development.

I am trying to store a file in PostgreSQL Bytea column because the application needs to share resources with Java Web Services.

However, when I try to retrieve the data (the contents of the file) back, I cannot recreate the file.

The error message is Resource #92. I searched only online and people said that Resource #92 means I should not print the nonprintable contents. It seems to me that the file_put_contents() expects unpacked data.

Anybody has experiences in recreating file/image from bytea data stores in PostgreSQL.

Please point me out to the right direction.

Here are my PHP Codes




class Doc extends CApplicationComponent {

	

	public function __construct() {

		

	}

	/**

	 * Build requested path using application root path and requested dir and file name 

	 * @param string $dir the requested directory  name

	 * @param string $filename the requested file name

	 * @return string the full path  

	 */

	public function createPath($dir, $fileName=null) {

		$basePath = Yii::app()->basePath;	

		$pos=strrpos($basePath,'/');

		$path = substr($basePath, 0, $pos + 1);

		if ($fileName != null)

			return ($path . $dir . '/' . $fileName);

		else 

			return ($path . $dir);

	}

	/**

	 * Create a directory in the root folder of the application

	 * @param string $dir for example 'files' or 'files/docs' or 'files/images' if 'files' already exists

	 * @return boolean true for success otherwise false 

	 */

	public function createDir($dir) {

		$flag=false;

		$path = $this->createPath($dir);

		if(file_exists($path) && is_dir($path))

			return $flag;

		else {			

			mkdir($path, '0755');

			$flag=true;

		}

		return $flag;

	}

	/**

	 * Saves the document in binary format 

	 * @param string $path the folter to be save. For exmample, files/docs 

	 * @param string $name the document file name. For examplle, test.rtf  

	 * @return integer 0 for failure of greater than 0 for success 

	 */

 	public function saveDocument($path, $name, $docTypeId) {

 		$id = 0;

 		$document = new Documents();

		$contents = $this->getFileBin($path, $name);

		if ($contents == null || strlen($contents) < 0) return $id;

		$docPath = $this->createPath($path, $name);

		$docExt = substr($docPath,strrpos($docPath,'.'));

		$docSize = strlen($contents);

		$document->setAttributes(

			array(

				'document_name' => $name,

				'document_data' => $contents,

				'document_path' => $docPath,

				'document_ext' => $docExt,

				'document_type_id' => $docTypeId,

				'document_size' => $docSize,

				'active' => true,

				'modified_at' => new CDbExpression('NOW()'),

			)

		);

		$document->save(false);

		return ($id = $document->id);

 	}

	/**

	 * Gets document by requested id

	 * @param integer $id the document id of requested record 

	 * @return instance of Documents object if success otherwise null 

	 */

	public function getDocumentById($id) {

		if ($id < 1) return null;

		return Documents::model()->findByPk($id);	

	}

	/**

	 * Gets file contents in binary format given a full path and file name

	 * We can use file_get_contents()  or fread() with 'rb' mode

	 * @param string $path the path to the folder that store the requested file

	 * @param string $name the requested file name 

	 * @return the binary data prepared for bytea colunmn of postgresql 

	 */

	public function getFileBin($path, $name) {

		$contents = '';

		$fullPath = $this->createPath($path);

		$dir = opendir($fullPath);

		while($file = readdir($dir)) {

			if (strcasecmp($name, $file) == 0) {

				$contents = file_get_contents($fullPath.'/'.$file);

				$contents = pg_escape_bytea($contents);	

				break;

			}

		}

		return $contents;

	}

	/**

	 * Creates file in original format given the binary file contents, the directory name, and the filename

	 * @param string $contents the contents of the document in binary format

	 * @param string $dir the directory name 

	 * @param string $name the document or file name 

	 * @return boolean true for success otherwise false 

	 * pg_unescape_bytea() 

	 */

	public function bin2File($contents, $dir, $name) {

		$contents = pg_unescape_bytea($contents);

		$fileName = $this->createPath($dir, $name);

		$bytes = file_put_contents($fileName, $contents);

		return (sizeof($bytes) > 0);

	}

	

}




Here are my PHP codes for Unit Test




class DocTest extends CTestCase  {

		

	protected $doc;

	

	protected function setUp() {

		$this->doc = new Doc();

	}

	

	protected function tearDown() {

		if (isset($this->doc)) unset($this->doc);

	}

	

	public function testGetFileBin() {

		$path = 'files/docs';

		$name = 'PartnershipAgreement.rtf';

		$contents = $this->doc->getFileBin($path, $name);

		echo "\ncontents = " . $contents . "\n";

		$this->assertTrue(strlen($contents) > 0);		

	}

	

	

	public function testGetDocumentById() {

		$document = $this->doc->getDocumentById(2);	

	}

	

	public function testBin2File() {

		$contents =null; 

		$dir = "files/docs";

		$name = "test.rtf";

		$document = $this->doc->getDocumentById(2);	

		echo $this->doc->createPath($dir,$name);

		$contents = $document->document_data;

		$flag = $this->doc->bin2File($contents, $dir, $name);

		$this->assertTrue($flag);

	}

	

	public function testSaveDocument() {

		$docTypeId = 4;

		$name = 'NonDisclosureAgreement.rtf';

		$path = 'files/docs';

		$contents = $this->doc->getFileBin($path, $name);

		$id = $this->doc->saveDocument($path, $name, $docTypeId);

		$this->assertTrue($id > 0);

	}


	public function testCreateDir() {

		$flag = $this->doc->createDir('files/images');

		$this->assertTrue($flag);	

	}

	

	public function testCreatePath() {

		$imgPath = $this->doc->createPath('images');

		echo "\nimage path = " . $imgPath . "\n";

		$imgFullPath = $this->doc->createpath('images', 'test.png');

		echo "image full path = " . $imgFullPath . "\n";

		$this->assertTrue(strlen($imgPath) > 0);

	}	

	

}



How did you solve this? Can you successfully store and retrieve blobs from psql dbms?