Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Eduiagami

Usando MeioUpload no Cakephp 2.0

Recommended Posts

Olá Galera,

-

Recentemente voltei a me aventurar na nova receita do Cakephp a versão 2.0.

Estou desenvolvendo um novo sistema e precisei de um upload rápido e fácil.

 

Pensando nisso resolvi baixar o component MeioUpload que há havia usado em outros projetos com versões anteriores.

O problema é que para utilizar o MeioUpload na nova versão do cakephp é necessário algumas modificações no componente, segue abaixo as modificações iniciais que tive que fazer, caso eu acho mais alguma edito este post com as novas.

abraços galera!

 

 

#linha 63 => troque por isto
App::uses('Folder','Utility');

#linha 370 => a Class Folder não mais implementa o metodo mkdir, agora utilize: create
if(!$this->Folder->create($options['dir'])) {

 

Espero que tenha ajudado.

Qualquer erro ou feedback comentem galera.

 

\o

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá, comigo ocorreu um erro não sei se é por que eu não estou utilizando o componente thumb, mas quando tento fazer o upload de uma imagem aparece a mensagem "o arquivo não pode ser vazio", sendo que eu seleciono um arquivo .png

Se alguém puder ajudar, eu agradeço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Eduiagami.

Eu configurei para a versão 2.1, e tive sucesso. Precisei mudar os links para o javascript também ficou assim:

<?php
/**
* MeioUpload Behavior
* This behavior is based on Tane Piper's improved uplaod behavior (http://digitalspaghetti.tooum.net/switchboard/blog/2497:Upload_Behavior_for_CakePHP_12)
* @author Vinicius Mendes (vbmendes@gmail.com)
* @link http://www.meiocodigo.com
* @filesource http://www.meiocodigo.com/meioupload
* @version 1.0.1
* @lastmodified 2008-10-04
* 
* Usage:
* 1) Download this behaviour and place it in your models/behaviours/upload.php
* 2) If you require thumbnails for image generation, download Nate's phpThumb Component (http://bakery.cakephp.org/articles/view/phpthumb-component)
* 3) Insert the following SQL into your database.  This is a basic model you can expand on:
*   CREATE TABLE `images` (
*       `id` int(8) unsigned NOT NULL auto_increment,
*    `filename` varchar() default NULL,
*    `dir` varchar(255) default NULL,
*    `mimetype` varchar(255) NULL,
*    `filesize` int(11) unsigned default NULL,
*    `created` datetime default NULL,
*    `modified` datetime default NULL,
*    PRIMARY KEY  (`id`) ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
* 4) In your model that you want to have the upload behavior work, place the below code.  This example is for an Image model:
* 
* var $actsAs = array('Upload' => array(
*       'filename' => array(
*           'dir' => 'files/images',
*           'create_directory' => false,
*           'allowed_mime' => array('image/jpeg', 'image/pjpeg', 'image/gif', 'image/png'),
*           'allowed_ext' => array('.jpg', '.jpeg', '.png', '.gif'),
*           'thumbsizes' => array(
*                  'small'  => array('width'=>100, 'height'=>100),
*                  'medium' => array('width'=>220, 'height'=>220),
*                  'large'  => array('width'=>800, 'height'=>600)
*           )
*       )
*     )
* );
* The above code will save the uploaded file's name in the 'filename' field in database,
* it will not overwrite existing files, instead it will create a new filename based on the original
* plus a counter.
* Allowed Mimetypes and extentions should be pretty explanitory.
* For thumbnails, when the file is uploaded, it will create 3 thumbnail sizes and prepend the name
* to the thumbfiles (i.e. image_001.jpg will produced thumb.small.image_001.jpg, thumb.medium.image_001.jpg, etc)
* 
* 5) Create your upload view, make sure it's a multipart/form-data form, and the filename field is of type $form->file
* 6) Make sure your directory is at least CHMOD 775, also check your php.ini MAX_FILE_SIZE is enough to support the filesizes you are uploading
* 
* Version Details
* 
* 1.0.1
* + Fixed a bug in the create folder method
* + Now you can use the $validate var of the model to apply the changes to default validation rules;
* + Changed the my_array_merge function, now it's part of the behavior, name arrayMerge;
* + Allow use of {DS}, {model} and {field} constants in directory name and fields names;
* + Fixed a bug with the replacement of the default names.
* 
* 1.0
* + Initial release.
* MODIFIED TO WORK IN CAKEPHP VERSION 2.1, BY CLAUDIO ZANA DOS SANTOS
* EARLIER CREDITS MUST BE KEPT. 
*/

App::uses('Folder','Utility');

class MeioUploadBehavior extends ModelBehavior {
/**
 * The default options for the behavior
 */

 public $default_options = array(
	'dir' => '',
	'allowed_mime' => array(),
	'allowed_ext' => array(),
	'create_directory' => true,
	'max_size' => 200097152,
	'fields' => array(
		'dir' => 'dir',
		'filesize' => 'filesize',
		'mimetype' => 'mimetype'
	),
	'validations' => array(
		'FieldName' => array(
			'rule' => array('uploadCheckFieldName'),
			'check' => true,
			'message' => 'Este campo não foi definido entre os parâmetros do MeioUploadBehavior.'
		),
		'Dir' => array(
			'rule' => array('uploadCheckDir'),
			'check' => true,
			'message' => 'O diretório onde este arquivo seria colocado não existe ou é protegido contra escrita.'
		),
		'Empty' => array(
			'rule' => array('uploadCheckEmpty'),
			'check' => true,
			'on' => 'create',
			'message' => 'O arquivo não pode ser vazio'
		),
		'UploadError' => array(
			'rule' => array('uploadCheckUploadError'),
			'check' => true,
			'message' => 'Ocorreram problemas no upload do arquivo.'
		),
		'MaxSize' => array(
			'rule' => array('uploadCheckMaxSize'),
			'check' => true,
			'message' => 'O tamanho máximo de arquivo foi excedido.'
		),
		'InvalidMime' => array(
			'rule' => array('uploadCheckInvalidMime'),
			'check' => true,
			'message' => 'Tipo de arquivo inválido.'
		),
		'InvalidExt' => array(
			'rule' => array('uploadCheckInvalidExt'),
			'check' => true,
			'message' => 'Extensão de arquivo inválida.'
		)
	)
);

 public $default_validations = array(
	'FieldName' => array(
		'rule' => array('uploadCheckFieldName'),
		'check' => true,
		'message' => 'Este campo não foi definido entre os parâmetros do MeioUploadBehavior.'
	),
	'Dir' => array(
		'rule' => array('uploadCheckDir'),
		'check' => true,
		'message' => 'O diretório onde este arquivo seria colocado não existe ou é protegido contra escrita.'
	),
	'Empty' => array(
		'rule' => array('uploadCheckEmpty'),
		'check' => true,
		'on' => 'create',
		'message' => 'O arquivo não pode ser vazio'
	),
	'UploadError' => array(
		'rule' => array('uploadCheckUploadError'),
		'check' => true,
		'message' => 'Ocorreram problemas no upload do arquivo.'
	),
	'MaxSize' => array(
		'rule' => array('uploadCheckMaxSize'),
		'check' => true,
		'message' => 'O tamanho máximo de arquivo foi excedido.'
	),
	'InvalidMime' => array(
		'rule' => array('uploadCheckInvalidMime'),
		'check' => true,
		'message' => 'Tipo de arquivo inválido.'
	),
	'InvalidExt' => array(
		'rule' => array('uploadCheckInvalidExt'),
		'check' => true,
		'message' => 'Extensão de arquivo inválida.'
	)
);

/**
 * The message for move error.
 */
 public $moveErrorMsg = 'Ocorreram problemas na cópia do arquivo.';

/**
 * The array that saves the $options for the behavior
 */
 public $__fields = array();

/**
 * Patterns of reserved words
 */
 public $patterns = array(
	"thumb",
	"default"
);

/**
 * Words to replace the patterns of reserved words
 */
 public $replacements = array(
	"t_umb",
	"d_fault"
);

/**
 * Array of files to be removed on the afterSave callback
 */
 public $__filesToRemove = array();

/**
 * Setup the behavior. It stores a reference to the model, merges the default options with the options for each field, and setup the validation rules.
 * 
 * @author Vinicius Mendes
 * @return null
 * @param $model Object
 * @param $config Array[optional]
 */
 function setup(&$model, $config=array()) {
	$this->Folder = &new Folder;
	$this->__model = $model;
	$this->__fields = array();
	foreach($config as $field => $options) {

		// Check if given field exists
		if(!$model->hasField($field)) {
			trigger_error('MeioUploadBehavior Error: The field "'.$field.'" doesn\'t exists in the model "'.$model->name.'".', E_USER_WARNING);
		}

		// Merge given options with defaults
		$options = $this->arrayMerge($this->default_options, $options);
		// Including the default name to the replacements

		// Process the max_size if it is not numeric
		$options['max_size'] = $this->sizeToBytes($options['max_size']);
		$this->__fields[$field] = $options;


		// Generate temporary directory if none provided
		if(empty($options['dir'])) {
			$this->__fields[$field]['dir'] = 'uploads' . DS . $model->name;
		// Else replace the tokens of the dir.
		} else {
			$this->__fields[$field]['dir'] = $this->replaceTokens($options['dir'],$field);
		}

		// Replace tokens in the fields names.
		foreach($this->__fields[$field]['fields'] as $fieldToken => $fieldName){
			$this->__fields[$field]['fields'][$fieldToken] = $this->replaceTokens($fieldName,$field);
		}

		// Check that the given directory does not have a DS on the end
		if($options['dir'][strlen($options['dir'])-1] == DS) {
			$options['dir'] = substr($options['dir'],0,strlen($options['dir'])-2);
		}
	}
}

/**
 * Merges two arrays recursively
 * 
 * @author Vinicius Mendes
 * @return Array
 * @param $arr Array
 * @param $ins Array
 */
 function arrayMerge($arr, $ins) {
	if (is_array($arr)) {
		if (is_array($ins)) {
			foreach ($ins as $k=>$v) {
				if (isset($arr[$k])&&is_array($v)&&is_array($arr[$k])) {
					$arr[$k] = $this->arrayMerge($arr[$k],$v);
				}
				else $arr[$k] = $v;
			}
		}
	} elseif (!is_array($arr)&&(strlen($arr)==0||$arr==0)) {
		$arr=$ins;
	}
	return($arr);
}

/**
 * Replaces some tokens. {model} to the underscore version of the model name, {field} to the field name, {DS}. / or \ to DS constant value.
 * 
 * @author Vinicius Mendes
 * @return String
 * @param $string String
 * @param $fieldName String
 */	
 function replaceTokens($string,$fieldName){
	return str_replace(array('{model}', '{field}', '{DS}','/','\\'),array(Inflector::underscore($this->__model->name),$fieldName,DS,DS,DS),$string);
}

/**
 * Convert a size value to bytes. For example: 2 MB to 2097152.
 * 
 * @author Vinicius Mendes
 * @return int
 * @param $size String
 */
 function sizeToBytes($size){
	if(is_numeric($size)) return $size;
	if(!preg_match('/^[1-9][0-9]* (kb|mb|gb|tb)$/i', $size)){
		trigger_error('MeioUploadBehavior Error: The max_size option format is invalid.', E_USER_ERROR);
		return 0;
	}
	list($size, $unit) = explode(' ',$size);
	if(strtolower($unit) == 'kb') return $size*1024;
	if(strtolower($unit) == 'mb') return $size*1048576;
	if(strtolower($unit) == 'gb') return $size*1073741824;
	if(strtolower($unit) == 'tb') return $size*1099511627776;
	trigger_error('MeioUploadBehavior Error: The max_size unit is invalid.', E_USER_ERROR);
	return 0;
}

/**
 * Sets the validation for each field, based on the options.
 * 
 * @author Vinicius Mendes
 * @return null
 * @param $fieldName String
 * @param $options Array
 */
 function setupValidation($fieldName, $options){
	$options = $this->__fields[$fieldName];

	if(isset($this->__model->validate[$fieldName])){
		if(isset($this->__model->validate[$fieldName]['rule'])){
			$this->__model->validate[$fieldName] = array(
				'oldValidation' => $this->__model->validates[$fieldName]
			);
		}
	} else {
		$this->__model->validate[$fieldName] = array();
	}
	$this->__model->validate[$fieldName] = $this->arrayMerge($this->default_validations,$this->__model->validate[$fieldName]);
	$this->__model->validate[$fieldName] = $this->arrayMerge($options['validations'],$this->__model->validate[$fieldName]);
}

/**
 * Checks if the field was declared in the MeioUpload Behavior setup
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $model Object
 * @param $data Array
 */
 function uploadCheckFieldName(&$model, $data,$other){
	foreach($data as $fieldName => $field){
		if(!$this->__model->validate[$fieldName]['FieldName']['check']) return true;
		if(isset($this->__fields[$fieldName])){
			return true;
		} else {
			$this->log('UploadBehavior Error: The field "'.$fieldName.'" wasn\'t declared as part of the UploadBehavior in model "'.$model->name.'".');
			return false;
		}
	}
	return true;
}

/**
 * Checks if the folder exists or can be created or writable.
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $model Object
 * @param $data Array
 */
 function uploadCheckDir(&$model, $data){
	foreach($data as $fieldName => $field){
		if(!$this->__model->validate[$fieldName]['Dir']['check']) return true;
		$options = $this->__fields[$fieldName];
		if(empty($field['remove']) || empty($field['name'])){
			// Check if directory exists and create it if required
			if(!is_dir($options['dir'])) {
				if($options['create_directory']){
					if(!$this->Folder->mkdir($options['dir'])) {
						trigger_error('UploadBehavior Error: The directory '.$options['dir'].' does not exist and cannot be created.', E_USER_WARNING);
						return false;
					}
				} else {
					trigger_error('UploadBehavior Error: The directory'.$options['dir'].' does not exist.', E_USER_WARNING);
					return false;
				}
			}

			// Check if directory is writable
			if(!is_writable($options['dir'])) {
				trigger_error('UploadBehavior Error: The directory '.$options['dir'].' isn\'t writable.', E_USER_WARNING);
				return false;
			}
		}
	}
	return true;
}

/**
 * Checks if the filename is not empty.
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $model Object
 * @param $data Array
 */
 function uploadCheckEmpty(&$model, $data){
	foreach($data as $fieldName => $field){
		if(!$this->__model->validate[$fieldName]['Empty']['check']) return true;
		if(empty($field['remove'])){
			if(!is_array($field) || empty($field['name'])){
				return false;
			}
		}
	}
	return true;
}

/**
 * Checks if ocurred erros in the upload.
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $model Object
 * @param $data Array
 */
 function uploadCheckUploadError(&$model, $data){
	foreach($data as $fieldName => $field){
		if(!$this->__model->validate[$fieldName]['UploadError']['check']) return true;
		if(!empty($field['name']) && $field['error'] > 0){
			return false;
		}
	}
	return true;
}

/**
 * Checks if the file isn't bigger then the max file size option.
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $model Object
 * @param $data Array
 */
 function uploadCheckMaxSize(&$model, $data){
	foreach($data as $fieldName => $field){
		if(!$this->__model->validate[$fieldName]['MaxSize']['check']) return true;
		$options = $this->__fields[$fieldName];
		if(!empty($field['name']) && $field['size'] > $options['max_size']) {
			return false;
		}
	}
	return true;
}

/**
 * Checks if the file is of an allowed mime-type.
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $model Object
 * @param $data Array
 */
 function uploadCheckInvalidMime(&$model, $data){
	foreach($data as $fieldName => $field){
		if(!$this->__model->validate[$fieldName]['InvalidMime']['check']) return true;
		$options = $this->__fields[$fieldName];
		if(!empty($field['name']) && count($options['allowed_mime']) > 0 && !in_array($field['type'], $options['allowed_mime'])) {
			return false;
		}
	}
	return true;
}

/**
 * Checks if the file has an allowed extension.
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $model Object
 * @param $data Array
 */
 function uploadCheckInvalidExt(&$model, $data){
	foreach($data as $fieldName => $field){
		if(!$this->__model->validate[$fieldName]['InvalidExt']['check']) return true;
		$options = $this->__fields[$fieldName];
		if(!empty($field['name'])){
			if(count($options['allowed_ext']) > 0) {
				$matches = 0;
				foreach($options['allowed_ext'] as $extension) {
					if(substr($field['name'],-strlen($extension)) == $extension) {
						$matches++;
					}
				}

				if($matches == 0) {
					return false;
				}
			}
		}
	}
	return true;
}

/**
 * Set a file to be removed in afterSave callback
 * 
 * @author Vinicius Mendes
 * @return null
 * @param $fieldName String
 */
 function setFileToRemove($fieldName){
	$filename = $this->__model->field($fieldName);
	if(!empty($filename) && $filename != $this->__fields[$fieldName]['default']){
		$this->__filesToRemove[] = array(
			'dir' => $this->__fields[$fieldName]['dir'],
			'name' => $filename
		);
	}
}

/**
 * Include a pattern of reserved word based on a filename, and it's replacement.
 * 
 * @author Vinicius Mendes
 * @return null
 * @param $default String
 */
 function _includeDefaultReplacement($default){
	$replacements = $this->replacements;
	list($newPattern, $ext) = $this->splitFilenameAndExt($default);
	if(!in_array($newPattern, $this->patterns)){
		$this->patterns[] = $newPattern;
		$newReplacement = $newPattern;
		if(isset($newReplacement[1])){
			if($newReplacement[1] != '_'){
				$newReplacement[1] = '_';
			} else {
				$newReplacement[1] = 'a';
			}
		} elseif($newReplacement != '_') {
			$newReplacement = '_';
		} else {
			$newReplacement = 'a';
		}
		$this->replacements[] = $newReplacement;
	}
}

/**
 * Removes the bad characters from the $filename and replace reserved words. It updates the $model->data.
 * 
 * @author Vinicius Mendes
 * @return null
 * @param $fieldName String
 */
 function fixName($fieldName){
	// updates the filename removing the keywords thumb and default name for the field.
	list($filename, $ext) = $this->splitFilenameAndExt($this->__model->data[$this->__model->name][$fieldName]['name']);
	$filename = str_replace($this->patterns,$this->replacements,$filename);
	$filename = Inflector::slug($filename);
	$i = 0;
	$newFilename = $filename;	
	while(file_exists($this->__fields[$fieldName]['dir'].DS.$newFilename.'.'.$ext)){
		$newFilename = $filename.$i;
		$i++;
	}
	$this->__model->data[$this->__model->name][$fieldName]['name'] = $newFilename.'.'.$ext;
}

/**
 * Splits a filename in two parts: the name and the extension. Returns an array with it respectively.
 * 
 * @author Vinicius Mendes
 * @return Array
 * @param $filename String
 */
 function splitFilenameAndExt($filename){
	$parts = explode('.',$filename);
	$ext = $parts[count($parts)-1];
	unset($parts[count($parts)-1]);
	$filename = implode('.',$parts);
	return array($filename,$ext);
}

/**
 * Sets the validation rules for each field.
 * 
 * @return true 
 * @param $model Object
 */
 function beforeValidate(&$model) {
	foreach($this->__fields as $fieldName=>$options){
		$this->setupValidation($fieldName, $options);
	}
	return true;
}

/**
 * Uploads the files before saving the record.
 * 
 * @author Vinicius Mendes 
 * @param $model Object
 */
 function beforeSave(&$model) {
	foreach($this->__fields as $fieldName=>$options){
		// if the file is marked to be deleted, use the default or set the field to null
		if(!empty($model->data[$model->name][$fieldName]['remove'])){
			if($options['default']){
				$model->data[$model->name][$fieldName] = $options['default'];
			} else {
				$model->data[$model->name][$fieldName] = null;
			}
			//if the record is already saved in the database, set the existing file to be removed after the save is sucessfull
			if(!empty($model->data[$model->name][$model->primaryKey])){
				$this->setFileToRemove($fieldName);
			}
			continue;
		}


		//Se nenhum arquivo foi atualizado, então tira o registro o campo do campo para evitar sobreescrever o arquivo existente
		// If no file has been upload, then unset the field to avoid overwriting existant file 
		if(!isset($model->data[$model->name][$fieldName]) || !is_array($model->data[$model->name][$fieldName]) || empty($model->data[$model->name][$fieldName]['name'])){
			if(!empty($model->data[$model->name][$model->primaryKey]) || !$options['default']){
				unset($model->data[$model->name][$fieldName]);
			} else {
				$model->data[$model->name][$fieldName] = $options['default'];
			}
			continue;
		}

		//Se o registro ja foi salvo no banco, seta um arquivo existente para ser removido depois de salvo com sucesso. 
		//if the record is already saved in the database, set the existing file to be removed after the save is sucessfull
		if(!empty($model->data[$model->name][$model->primaryKey])){
			$this->setFileToRemove($fieldName);
		}

		// Fix the filename, removing bad characters and avoiding from overwriting existing ones
		$this->_includeDefaultReplacement($options['default']);
		$this->fixName($fieldName);
		$saveAs = $options['dir'].DS.$model->data[$model->name][$fieldName]['name'];

		// Attempt to move uploaded file
		if(!move_uploaded_file($model->data[$model->name][$fieldName]['tmp_name'], $saveAs)){
			$model->validationErrors[$field] = $moveErrorMsg;
			return false;
		}



		// Update model data
		$model->data[$model->name][$options['fields']['dir']] = $options['dir'];
		$model->data[$model->name][$options['fields']['mimetype']] =  $model->data[$model->name][$fieldName]['type'];            
		$model->data[$model->name][$options['fields']['filesize']] = $model->data[$model->name][$fieldName]['size'];
		$model->data[$model->name][$fieldName] = $model->data[$model->name][$fieldName]['name'];
	}
	return true;
}

/**
 * Deletes the files marked to be deleted in the save method. A file can be marked to be deleted if it is overwriten by another or if the user mark it to be deleted.
 * 
 * @author Vinicius Mendes 
 * @param $model Object
 */
 function afterSave(&$model) {
	foreach($this->__filesToRemove as $file){
		if($file['name'])
			$this->_deleteFiles($file['name'], $file['dir']);			
	}
	// Reset the filesToRemove array
	$this->__filesToRemove = array();
}

/**
 * Deletes all files associated with the record beforing delete it.
 * 
 * @author Vinicius Mendes 
 * @param $model Object
 */   
 function beforeDelete(&$model) {
	$model->read(null, $model->id);
	if(isset($model->data)) {
		foreach($this->__fields as $field=>$options) {
			$file = $model->data[$model->name][$field];
			if($file && $file != $options['default'])
				$this->_deleteFiles($file, $options['dir']);
		}
	}
	return true;
}

/**
 * Delete the $filename inside the $dir and the thumbnails.
 * Returns true if the file is deleted and false otherwise.
 * 
 * @author Vinicius Mendes
 * @return boolean
 * @param $filename Object
 * @param $dir Object
 */
 function _deleteFiles($filename, $dir){
	$saveAs = $dir . DS . $filename;
	if(is_file($saveAs) && !unlink($saveAs))
	{
		return false;
	}
	$folder = &new Folder($dir);
	//$files = $folder->find('thumb\.[a-zA-Z0-9]+\.'.$filename);
	foreach($files as $f) unlink($dir.DS.$f);
	return true;
}



}
?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.