Khanh Hoang - Kenn
Kenn is a user experience designer and front end developer who enjoys creating beautiful and usable web and mobile experiences.
Đối với các ứng dụng online thì module Upload ảnh là một thành phần không thể thiếu. Trong bài viết này , tôi sẽ hướng dẫn các bạn sử dụng Componet Upload để upload ảnh. Cụ thể trong ví dụ này tôi sẽ có Controller tên Images , sử dụng Component có tên Upload ,để thực hiện việc upload ảnh . Sau đó lưu tên vừa upload vào CSDL và hiển thị ảnh vừa upload ra ngoài.- B1 : Tạo table tên Images
PHP Code:
CREATE TABLE `#DD0000">images` (
`#DD0000">id` int(11) NOT NULL AUTO_INCREMENT,
`#DD0000">images` longtext NOT NULL,
PRIMARY KEY (`#DD0000">id`)
)- B2 : Tạo component Upload
Vào thư mục “app/controllers/components/” tạo file upload.php với nội dung sau :
PHP Code:
<?php
class UploadComponent extends Object {
#FF8000">/**
* Private Vars
*/
var $_file;
var $_filepath;
var $_destination;
var $_name;
var $_short;
var $_rules;
var $_allowed;
#FF8000">/**
* Public Vars
*/
var $errors;
#FF8000">//----- Template Component ----
//called before Controller::beforeFilter()
function initialize(&$controller, $settings = array()) {
#FF8000">// saving the controller reference for later use
$this->controller =& $controller;
}
#FF8000">//called after Controller::beforeRender()
function beforeRender(&$controller) {
}
#FF8000">//called after Controller::render()
function shutdown(&$controller) {
}
#FF8000">//called before Controller::redirect()
function beforeRedirect(&$controller, $url, $status=null, $exit=true) {
}
function redirectSomewhere($value) {
#FF8000">// utilizing a controller method
}
#FF8000">//---------------------------------------------------
function startup (&$controller) {
#FF8000">// This method takes a reference to the controller which is loading it.
// Perform controller initialization here.
}
#FF8000">/**
* upload
* - handle uploads of any type
* @ file - a file (file to upload) $_FILES[FILE_NAME]
* @ path - string (where to upload to)
* @ name [optional] - override saved filename
* @ rules [optional] - how to handle file types
* - rules['type'] = string ('resize','resizemin','resizecrop','crop')
* - rules['size'] = array (x, y) or single number
* - rules['output'] = string ('gif','png','jpg')
* - rules['quality'] = integer (quality of output image)
* @ allowed [optional] - allowed filetypes
* - defaults to 'jpg','jpeg','gif','png'
* ex:
* $upload = new upload($_FILES['MyFile'], 'uploads');
*
*/
function upload ($file, $destination, $name = NULL, $rules = NULL, $allowed = NULL) {
$this->result = false;
$this->error = false;
#FF8000">// -- save parameters
$this->_file = $file;
$this->_destination = $destination;
if (!is_null($rules)) $this->_rules = $rules;
if (!is_null($allowed)) { $this->_allowed = $allowed; } else { $this->_allowed = array(#DD0000">'jpg',#DD0000">'jpeg',#DD0000">'gif',#DD0000">'png'); }
#FF8000">// -- hack dir if / not provided
if (substr($this->_destination,-1) != #DD0000">'/') {
$this->_destination .= #DD0000">'/';
}
#FF8000">// -- check that FILE array is even set
if (isset($file) && is_array($file) && !$this->upload_error($file[#DD0000">'error'])) {
#FF8000">// -- cool, now set some variables
$fileName = ($name == NULL) ? $this->uniquename($destination . $file[#DD0000">'name']) : $destination . $name;
$fileTmp = $file[#DD0000">'tmp_name'];
$fileSize = $file[#DD0000">'size'];
$fileType = $file[#DD0000">'type'];
$fileError = $file[#DD0000">'error'];
#FF8000">// -- update name
$this->_name = $fileName;
#FF8000">// -- error if not correct extension
if(!in_array($this->ext($fileName),$this->_allowed)){
$this->error(#DD0000">"File type not allowed.");
} else {
#FF8000">// -- it's been uploaded with php
if (is_uploaded_file($fileTmp)) {
#FF8000">// -- how are we handling this file
if ($rules == NULL) {
#FF8000">// -- where to put the file?
$output = $fileName;
#FF8000">// -- just upload it
if (move_uploaded_file($fileTmp, $output)) {
chmod($output, 0644);
$this->result = basename($this->_name);
} else {
$this->error(#DD0000">"Could not move '$fileName#DD0000">' to '$destination#DD0000">'");
}
} else {
#FF8000">// -- gd lib check
if (function_exists(#DD0000">"imagecreatefromjpeg")) {
if (!isset($rules[#DD0000">'output'])) $rules[#DD0000">'output'] = NULL;
if (!isset($rules[#DD0000">'quality'])) $rules[#DD0000">'quality'] = NULL;
#FF8000">// -- handle it based on rules
if (isset($rules[#DD0000">'type']) && isset($rules[#DD0000">'size'])) {
$this->image($this->_file, $rules[#DD0000">'type'], $rules[#DD0000">'size'], $rules[#DD0000">'output'], $rules[#DD0000">'quality']);
} else {
$this->error(#DD0000">"Invalid \"rules\" parameter");
}
} else {
$this->error(#DD0000">"GD library is not installed");
}
}
} else {
$this->error(#DD0000">"Possible file upload attack on '$fileName#DD0000">'");
}
}
} else {
$this->error(#DD0000">"Possible file upload attack");
}
}
#FF8000">// -- return the extension of a file
function ext ($file) {
$ext = trim(substr($file,strrpos($file,#DD0000">".")+1,strlen($file)));
return $ext;
}
#FF8000">// -- add a message to stack (for outside checking)
function error ($message) {
if (!is_array($this->errors)) $this->errors = array();
array_push($this->errors, $message);
}
function image ($file, $type, $size, $output = NULL, $quality = NULL) {
if (is_null($type)) $type = #DD0000">'resize';
if (is_null($size)) $size = 100;
if (is_null($output)) $output = #DD0000">'jpg';
if (is_null($quality)) $quality = 75;
#FF8000">// -- format variables
$type = strtolower($type);
$output = strtolower($output);
if (is_array($size)) {
$maxW = intval($size[0]);
$maxH = intval($size[1]);
} else {
$maxScale = intval($size);
}
#FF8000">// -- check sizes
if (isset($maxScale)) {
if (!$maxScale) {
$this->error(#DD0000">"Max scale must be set");
}
} else {
if (!$maxW || !$maxH) {
$this->error(#DD0000">"Size width and height must be set");
return;
}
if ($type == #DD0000">'resize') {
$this->error(#DD0000">"Provide only one number for size");
}
}
#FF8000">// -- check output
if ($output != #DD0000">'jpg' && $output != #DD0000">'png' && $output != #DD0000">'gif') {
$this->error(#DD0000">"Cannot output file as " . strtoupper($output));
}
if (is_numeric($quality)) {
$quality = intval($quality);
if ($quality > 100 || $quality < 1) {
$quality = 75;
}
} else {
$quality = 75;
}
#FF8000">// -- get some information about the file
$uploadSize = getimagesize($file[#DD0000">'tmp_name']);
$uploadWidth = $uploadSize[0];
$uploadHeight = $uploadSize[1];
$uploadType = $uploadSize[2];
if ($uploadType != 1 && $uploadType != 2 && $uploadType != 3) {
$this->error (#DD0000">"File type must be GIF, PNG, or JPG to resize");
}
switch ($uploadType) {
case 1: $srcImg = imagecreatefromgif($file[#DD0000">'tmp_name']); break;
case 2: $srcImg = imagecreatefromjpeg($file[#DD0000">'tmp_name']); break;
case 3: $srcImg = imagecreatefrompng($file[#DD0000">'tmp_name']); break;
default: $this->error (#DD0000">"File type must be GIF, PNG, or JPG to resize");
}
switch ($type) {
case #DD0000">'resize':
#FF8000"># Maintains the aspect ration of the image and makes sure that it fits
# within the maxW and maxH (thus some side will be smaller)
// -- determine new size
if ($uploadWidth > $maxScale || $uploadHeight > $maxScale) {
if ($uploadWidth > $uploadHeight) {
$newX = $maxScale;
$newY = ($uploadHeight*$newX)/$uploadWidth;
} else if ($uploadWidth < $uploadHeight) {
$newY = $maxScale;
$newX = ($newY*$uploadWidth)/$uploadHeight;
} else if ($uploadWidth == $uploadHeight) {
$newX = $newY = $maxScale;
}
} else {
$newX = $uploadWidth;
$newY = $uploadHeight;
}
$dstImg = imagecreatetruecolor($newX, $newY);
imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $newX, $newY, $uploadWidth, $uploadHeight);
break;
case #DD0000">'resizemin':
#FF8000"># Maintains aspect ratio but resizes the image so that once
# one side meets its maxW or maxH condition, it stays at that size
# (thus one side will be larger)
#get ratios
$ratioX = $maxW / $uploadWidth;
$ratioY = $maxH / $uploadHeight;
#FF8000">#figure out new dimensions
if (($uploadWidth == $maxW) && ($uploadHeight == $maxH)) {
$newX = $uploadWidth;
$newY = $uploadHeight;
} else if (($ratioX * $uploadHeight) > $maxH) {
$newX = $maxW;
$newY = ceil($ratioX * $uploadHeight);
} else {
$newX = ceil($ratioY * $uploadWidth);
$newY = $maxH;
}
$dstImg = imagecreatetruecolor($newX,$newY);
imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $newX, $newY, $uploadWidth, $uploadHeight);
break;
case #DD0000">'resizecrop':
#FF8000">// -- resize to max, then crop to center
$ratioX = $maxW / $uploadWidth;
$ratioY = $maxH / $uploadHeight;
if ($ratioX < $ratioY) {
$newX = round(($uploadWidth - ($maxW / $ratioY))/2);
$newY = 0;
$uploadWidth = round($maxW / $ratioY);
$uploadHeight = $uploadHeight;
} else {
$newX = 0;
$newY = round(($uploadHeight - ($maxH / $ratioX))/2);
$uploadWidth = $uploadWidth;
$uploadHeight = round($maxH / $ratioX);
}
$dstImg = imagecreatetruecolor($maxW, $maxH);
imagecopyresampled($dstImg, $srcImg, 0, 0, $newX, $newY, $maxW, $maxH, $uploadWidth, $uploadHeight);
break;
case #DD0000">'crop':
#FF8000">// -- a straight centered crop
$startY = ($uploadHeight - $maxH)/2;
$startX = ($uploadWidth - $maxW)/2;
$dstImg = imageCreateTrueColor($maxW, $maxH);
ImageCopyResampled($dstImg, $srcImg, 0, 0, $startX, $startY, $maxW, $maxH, $maxW, $maxH);
break;
default: $this->error (#DD0000">"Resize function \"$type#DD0000">\" does not exist");
}
#FF8000">// -- try to write
switch ($output) {
case #DD0000">'jpg':
$write = imagejpeg($dstImg, $this->_name, $quality);
break;
case #DD0000">'png':
$write = imagepng($dstImg, $this->_name . #DD0000">".png", $quality);
break;
case #DD0000">'gif':
$write = imagegif($dstImg, $this->_name . #DD0000">".gif", $quality);
break;
}
#FF8000">// -- clean up
imagedestroy($dstImg);
if ($write) {
$this->result = basename($this->_name);
} else {
$this->error(#DD0000">"Could not write " . $this->_name . #DD0000">" to " . $this->_destination);
}
}
function newname ($file) {
return time() . #DD0000">"." . $this->ext($file);
}
function uniquename ($file) {
$parts = pathinfo($file);
$dir = $parts[#DD0000">'dirname'];
$file = ereg_replace(#DD0000">'[^[:alnum:]_.-]',#DD0000">'',$parts[#DD0000">'basename']);
$ext = $parts[#DD0000">'extension'];
if ($ext) {
$ext = #DD0000">'.'.$ext;
$file = substr($file,0,-strlen($ext));
}
$i = 0;
while (file_exists($dir.#DD0000">'/'.$file.$i.$ext)) $i++;
return $dir.#DD0000">'/'.$file.$i.$ext;
}
function upload_error ($errorobj) {
$error = false;
switch ($errorobj) {
case UPLOAD_ERR_OK: break;
case UPLOAD_ERR_INI_SIZE: $error = #DD0000">"The uploaded file exceeds the upload_max_filesize directive (".ini_get(#DD0000">"upload_max_filesize").#DD0000">") in php.ini."; break;
case UPLOAD_ERR_FORM_SIZE: $error = #DD0000">"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form."; break;
case UPLOAD_ERR_PARTIAL: $error = #DD0000">"The uploaded file was only partially uploaded."; break;
case UPLOAD_ERR_NO_FILE: $error = #DD0000">"No file was uploaded."; break;
case UPLOAD_ERR_NO_TMP_DIR: $error = #DD0000">"Missing a temporary folder."; break;
case UPLOAD_ERR_CANT_WRITE: $error = #DD0000">"Failed to write file to disk"; break;
default: $error = #DD0000">"Unknown File Error";
}
return ($error);
}
}
?>- B3 : Tạo Controller Images
Vào thư mục “app/controllers/” tạo file images_controllers.php với nội dung sau :
PHP Code:
<?php
class ImagesController extends AppController {
var $name = #DD0000">'Images';
var $helpers = array(#DD0000">'Html', #DD0000">'Form');
var $components = array(#DD0000">'Upload'); #FF8000">// nạp Component upload
function index(){
$images = $this->Image->find(#DD0000">"all");
$this->set(#DD0000">"images",$images);
}
function upload() {
if (empty($this->data)) {
$this->render();
} else {
$data = $this->data;
#FF8000">// đường dẫn tới thu mục upload file ảnh
$destination = realpath(#DD0000">'../../app/webroot/img/uploads/') . #DD0000">'/';
#FF8000">// grab the file
$file = $this->data[#DD0000">'Image'][#DD0000">'filedata'];
#FF8000">// cấu hình upload
$rule = array(
#DD0000">'type' => #DD0000">'resizemin',
#DD0000">'size' => array(#DD0000">'400', #DD0000">'300'),
#DD0000">'output' => #DD0000">'jpg',
);
$result = $this->Upload->upload($file, $destination, null, $rule);
if (!$this->Upload->errors){
$data[#DD0000">'Image'][#DD0000">'images'] = $this->Upload->result;
} else {
#FF8000">// display error
$errors = $this->Upload->errors;
#FF8000">// piece together errors
if(is_array($errors)){ $errors = implode(#DD0000">"<br />",$errors); }
$this->Session->setFlash($errors);
$this->redirect(#DD0000">'/images/upload');
exit();
}
if ($this->Image->save($data)) {
$this->Session->setFlash(#DD0000">'Image has been added.');
$this->redirect(#DD0000">'/images/index');
} else {
$this->Session->setFlash(#DD0000">'Please correct errors below.');
unlink($destination.$this->Upload->result);
}
}
}
}
?>Giải thích :
Trong Controlller Images trên ta có 2 function chính :
- Index() : hiển thị danh sách ảnh đã upload từ CSDL
- Upload() : hiển thị form upload và chọn file ảnh để upload
- Phần :
$rule = array(
'type' => 'resizemin',
'size' => array('400', '300'),
'output' => 'jpg',
);
Là tập luật để upload ảnh : ảnh sẽ resize lại theo kích thướt 400px X 300px- B4 : Tạo thư mục chứa file upload và các file view cho function trong Controller Images
- Tạo thư mục chứa file : ta vào “app/webroot/img” tạo thư mục uploads , nơi đây sẽ
chứa các file được upload .
- Tạo file view : vào thư mục “app/views/” tạo thư mục images, sau đó trong thư
mục images , tạo 2 file index.ctp và upload.ctp tương ứng với 2 function của Controller
Images
File index.ctp :
PHP Code:
<div class="images">
<h2>List Images</h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th>Id</th>
<th>Image String</th>
<th>Image Display</th>
</tr>
<?php foreach ($images as $image): ?>
<tr>
<td><?php echo $image[#DD0000">'Image'][#DD0000">'id']; ?></td>
<td><?php echo $image[#DD0000">'Image'][#DD0000">'images']; ?></td>
<td>
<?php $string = $image[#DD0000">'Image'][#DD0000">'images']; ?>
<img src="<?=$this->webroot?>img/uploads/<?=$string?>" alt="*" />
</td>
</tr>
<?php endforeach; ?>
</table>
<ul class="actions">
<li><?php echo $this->Html->link(#DD0000">'Upload Images', #DD0000">'/images/upload'); ?></li>
</ul>
</div>File upload.ctp
PHP Code:
<h2>Upload An Image</h2>
<form action="<?php echo $this->Html->url(#DD0000">'/images/upload'); ?>" method="post" enctype="multipart/form-data">
<fieldset>
<legend>
Images
</legend>
<ul>
<li>
<?php echo $this->Form->file(#DD0000">'Image.filedata');?>
</li>
</ul>
</fieldset>
<p><input type="submit" name="add" value="Add Image" /></p>
</form>- B5 : Chạy thử ứng dụng : http://localhost/cakephp/images/upload
Kết quả sau khi upload thành công :
Bài viết tham khảo tại : http://labs.iamkoa.net/2007/10/23/im...onent-cakephp/