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很容易查出来,会报错,但是底层代码就需要大量时间去熟悉框架,最代码执行流程,一步一步测试
。