1.gd和imagick的区别
gd何imagick是图片处理的扩展,如缩小,裁剪,旋转,水印等。
imagick是一个面向对象的扩展,gd是提供一系列函数,所以代码编码质量imagick比gd好很多,不过php 5.3以后原生支持gd,相对来说gd更流行,也有很多gd的封装类可以使用
详细接对比访问:https://www.sitepoint.com/imagick-vs-gd/ 点击打开链接
2.yii2.0框架
这个框架性能好,安全,组件化编程,生成环境使用广泛,也是作为phper必不可少去学习使用的一个框架,集成了学习优秀的设计模式和编程风格,在工作和以后的面试的利器。
简单介绍下:像容器依赖,服务定位器,组件,行为,事件,方便的getter和setter,最核心的类是component类,没接触之前对这个框架印象是框架太大,肯定性能方面有欠缺,而且不是一个很容易入门的,学习时间会相对CI,TP比较长,但这个时间值得去学习。
因为有个base64编码文件上传的需求,如果用yii框架的话只能支持type=file的文件上传,所以需要在代码上做些改动。代码如下
public function __construct( $id, $module, $config = [] ) { header("Access-Control-Allow-Origin: *"); global $_FILES; if( !empty( $_POST["files"] ) && is_string($_POST['files']) ) { $tmpDir = dirname( dirname( __FILE__ ) ) . "/runtime/base64files/"; if(!file_exists($tmpDir)) { @mkdir( $tmpDir ,0755,true); } $file = $tmpDir . "php" . date("YmdHi") . rand(1000,9999) . ".tmp"; if(preg_match("/^(data:\s*image\/(\w+);base64,)/", $_POST['files'], $result)) { $base_file = str_replace($result[1],"",$_POST['files']); }else{ $base_file = $_POST['files']; } if( file_put_contents( $file, base64_decode( $base_file ) ) ) { $ext = $this->__getImageExt( $file ); $imageSizeInfo = @getimagesize( $file ); if( $ext ) { $fileName = date("YmdHi") . rand(10000,99999).$ext ; $_FILES = array ( 'files' => array ( 'name' => $fileName, 'type' => $imageSizeInfo[2], 'tmp_name' => $file, 'error' => 0, 'size' => @filesize( $file ), ), ); } else { // TODO var_dump( error_get_last()); exit; } } else { // TODO var_dump( error_get_last()); exit; } } parent::__construct($id, $module, $config); }
private function __getImageExt( $file = '' ) { $res = false; $imageSizeInfo = @getimagesize( $file ,$imageinfo); if( $imageSizeInfo ) { $mime_type = $imageSizeInfo[2]; switch ($mime_type) { case 1: case 'image/gif': $res = ".gif"; break; case 2: case 'image/pjpeg': case 'image/jpeg': $res = ".jpg"; break; case 3: case 'image/x-png': case 'image/png': $res = ".png"; break; default: return false; } } return $res; }
我简单模拟$_FILES的数据结构,为了方便集成到现有的文件上传系统,代码上改动相对少很多。但是由于yii2的文件上传验证器会判断文件的传输方式,使用is_uploaded_file,传输方式我没找到方法模拟,所以不能继续用yii2提供的image验证器,所以如果有文件上传方面的规则限制,需要另外实现,逻辑也不会太复杂,
public function validateBase64() { $rules = $this->rules(); if(isset($rules[0]['minWidth'])) { $this->minWidth = $rules[0]['minWidth']; } if(isset($rules[0]['minHeight'])) { $this->minHeight = $rules[0]['minHeight']; } if(isset($rules[0]['maxSize'])) { $this->maxSize = $rules[0]['maxSize']; } if(isset($rules[0]['extensions'])) { $this->extensions = $rules[0]['extensions']; } if(false === strpos($this->extensions,substr($_FILES['files']['name'] ,strpos($_FILES['files']['name'] ,'.')+1))) { $error = Yii::t('yii', "Only files with these extensions are allowed: {$this->extensions}."); $this->addError("files", $error); return false; } if($_FILES['files']['size'] >$this->maxSize) { $maxSize = round($this->maxSize/(1024),1);// $error= Yii::t('yii', "The file is too big. Its size cannot exceed {$maxSize} KB "); $this->addError("files", $error); return false; } $file_info = @getimagesize($_FILES['files']['tempName']); if($file_info) { if($file_info[0] < $this->minWidth || $file_info[1] < $this->minHeight) { $error = Yii::t('yii', "The file is too small. Its min width cannot be smaller than {$this->minWidth} and Its min height cannot be smaller than {$this->minHeight}"); $this->addError("files", $error); return false; } } else{ $error = Yii::t('yii', 'File upload failed.'); $this->addError("files", json_encode(error_get_last())); return false; } return true; }
保存文件的逻辑还是可以使用yii2提供的,简化代码,
/** * 上传 * * @param bool $tos3 * @return bool|string */ public function upload($tos3 = false) { //如果是base64上传的图片 if($this->isBaseImageData() ) { global $_FILES; $this->init(); if($this->validateBase64() && $this->save()) { //上传成功后的逻辑 return true; } // $this->addError("files", json_encode(error_get_last())); return false; } //正常file上传图片方式 if ($this->validate() && $this->save()) {// //
//上传成功后的逻辑
return true; } else { return false; } }
需要注意的是在yii的saveAs方法里面需要做下处理,以便兼容base64编码图片上传,可以通过判断保存临时文件的路径
如果是文件上传用move_uploaded_file,如果使用base64编码上传,用copy方法,记得复制后删除临时文件
图片处理可以用gd,也可以用imagick,两个扩展在处理png,jpg,jpeg之类的图片没啥区别,但是在处理gif图片的时候,生成相应的缩略图,会有点问题,writeImages($fileName,true)可以写gif到$fileName,根据官方文档是没问题的,但是在调试的时候,在处理gif图片时,会报错,直接返回false,异常捕获不到,挺奇怪的,
最初认为是代码问题,查到yii框架源码才发现使用的这个imagick扩展,因为本地用的是gd扩展,所以没有发现这个问题,在测试机上会出现这个问题,日志也没有报错。把处理图片的类换成使用gd扩展的类就行了。
3.总结
查问题需要查到框架源码的时候,可以意识到因为测试环境是linux,本地是windows,不同的地方有安装的扩展不完全相同,php版本是否不同。像业务代码的bug很容易查出来,会报错,但是底层代码就需要大量时间去熟悉框架,最代码执行流程,一步一步测试
。