9 760 2021-02-20 09:30:34
收藏帝国cms默认编辑器UEdito读取远程图片失效,失败的原因有2个,1是文件类型,也就是文件的扩展名验证不通过。2是当图片的地址后面带问号“?”,也就是地址后面带参数的时候,拉取远程图片会失败。
另外,验证时的扩展名问题解决了,就出现另一个问题,就是上传保存的实际的文件名没有扩展名。
获取扩展名是依赖原始文件名的:
$imgUrl="https://upload-images.jianshu.io/upload_images/13291551-ea2071894c84a625.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/544/format/webp"; preg_match("/[/]([^/]*)[.]?[^./]*$/",$imgUrl,$m); $this->oriName=$m?$m[1]:"";
这导致获取到的原始文件名是:/webp,原始文件名没有扩展名,就导致实际的文件名没有扩展名。
修改后的完整代码如下:
<?php classUploader { private$fileField;//文件域名 private$file;//文件上传对象 private$base64;//文件上传对象 private$config;//配置信息 private$oriName;//原始文件名 private$fileName;//新文件名 private$fullName;//完整文件名,即从当前配置目录开始的URL private$filePath;//完整文件名,即从当前配置目录开始的URL private$fileSize;//文件大小 private$fileType;//文件类型 private$stateInfo;//上传状态信息, private$stateMap=array(//上传状态映射表,国际化用户需考虑此处数据的国际化 "SUCCESS",//上传成功标记,在UEditor中内不可改变,否则flash判断会出错 "文件大小超出upload_max_filesize限制", "文件大小超出MAX_FILE_SIZE限制", "文件未被完整上传", "没有文件被上传", "上传文件为空", "ERROR_TMP_FILE"=>"临时文件错误", "ERROR_TMP_FILE_NOT_FOUND"=>"找不到临时文件", "ERROR_SIZE_EXCEED"=>"文件大小超出网站限制", "ERROR_TYPE_NOT_ALLOWED"=>"文件类型不允许", "ERROR_CREATE_DIR"=>"目录创建失败", "ERROR_DIR_NOT_WRITEABLE"=>"目录没有写权限", "ERROR_FILE_MOVE"=>"文件保存时出错", "ERROR_FILE_NOT_FOUND"=>"找不到上传文件", "ERROR_WRITE_CONTENT"=>"写入文件内容错误", "ERROR_UNKNOWN"=>"未知错误", "ERROR_DEAD_LINK"=>"链接不可用", "ERROR_HTTP_LINK"=>"链接不是http链接", "ERROR_HTTP_CONTENTTYPE"=>"链接contentType不正确", "ERROR_HTTP_ALLOWFILES"=>"抓取图片格式扩展名不正确", "INVALID_URL"=>"非法URL", "INVALID_IP"=>"非法IP" ); /** *构造函数 *@paramstring$fileField表单名称 *@paramarray$config配置项 *@parambool$base64是否解析base64编码,可省略。若开启,则$fileField代表的是base64编码的字符串表单名 */ publicfunction__construct($fileField,$config,$type="upload") { $this->fileField=$fileField; $this->config=$config; $this->type=$type; if($type=="remote"){ $this->saveRemote(); }elseif($type=="base64"){ $this->upBase64(); }else{ $this->upFile(); } $this->stateMap['ERROR_TYPE_NOT_ALLOWED']=iconv('unicode','utf-8',$this->stateMap['ERROR_TYPE_NOT_ALLOWED']); } /** *上传文件的主处理方法 *@returnmixed */ privatefunctionupFile() { $file=$this->file=$_FILES[$this->fileField]; if(!$file){ $this->stateInfo=$this->getStateInfo("ERROR_FILE_NOT_FOUND"); return; } if($this->file['error']){ $this->stateInfo=$this->getStateInfo($file['error']); return; }elseif(!file_exists($file['tmp_name'])){ $this->stateInfo=$this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND"); return; }elseif(!is_uploaded_file($file['tmp_name'])){ $this->stateInfo=$this->getStateInfo("ERROR_TMPFILE"); return; } $this->oriName=$file['name']; $this->fileSize=$file['size']; $this->fileType=$this->getFileExt(); $this->fullName=$this->getFullName(); $this->filePath=$this->getFilePath(); $this->fileName=$this->getFileName(); $dirname=dirname($this->filePath); //检查文件大小是否超出限制 if(!$this->checkSize()){ $this->stateInfo=$this->getStateInfo("ERROR_SIZE_EXCEED"); return; } //检查是否不允许的文件格式 if(!$this->checkType()){ $this->stateInfo=$this->getStateInfo("ERROR_TYPE_NOT_ALLOWED"); return; } //创建目录失败 if(!file_exists($dirname)&&!mkdir($dirname,0777,true)){ $this->stateInfo=$this->getStateInfo("ERROR_CREATE_DIR"); return; }elseif(!is_writeable($dirname)){ $this->stateInfo=$this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); return; } //移动文件 if(!(move_uploaded_file($file["tmp_name"],$this->filePath)&&file_exists($this->filePath))){//移动失败 $this->stateInfo=$this->getStateInfo("ERROR_FILE_MOVE"); }else{//移动成功 $this->stateInfo=$this->stateMap[0]; } } /** *处理base64编码的图片上传 *@returnmixed */ privatefunctionupBase64() { $base64Data=$_POST[$this->fileField]; $img=base64_decode($base64Data); $this->oriName=$this->config['oriName']; $this->fileSize=strlen($img); $this->fileType=$this->getFileExt(); $this->fullName=$this->getFullName(); $this->filePath=$this->getFilePath(); $this->fileName=$this->getFileName(); $dirname=dirname($this->filePath); //检查文件大小是否超出限制 if(!$this->checkSize()){ $this->stateInfo=$this->getStateInfo("ERROR_SIZE_EXCEED"); return; } //创建目录失败 if(!file_exists($dirname)&&!mkdir($dirname,0777,true)){ $this->stateInfo=$this->getStateInfo("ERROR_CREATE_DIR"); return; }elseif(!is_writeable($dirname)){ $this->stateInfo=$this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); return; } //移动文件 if(!(file_put_contents($this->filePath,$img)&&file_exists($this->filePath))){//移动失败 $this->stateInfo=$this->getStateInfo("ERROR_WRITE_CONTENT"); }else{//移动成功 $this->stateInfo=$this->stateMap[0]; } } /** *拉取远程图片 *@returnmixed */ privatefunctionsaveRemote() { $imgUrl=htmlspecialchars($this->fileField); $imgUrl=str_replace("&","&",$imgUrl); //http开头验证 if(strpos($imgUrl,"http")!==0){ $this->stateInfo=$this->getStateInfo("ERROR_HTTP_LINK"); return; } preg_match('/(^https*://[^:/]+)/',$imgUrl,$matches); $host_with_protocol=count($matches)>1?$matches[1]:''; //判断是否是合法url if(!filter_var($host_with_protocol,FILTER_VALIDATE_URL)){ $this->stateInfo=$this->getStateInfo("INVALID_URL"); return; } preg_match('/^https*://(.+)/',$host_with_protocol,$matches); $host_without_protocol=count($matches)>1?$matches[1]:''; //此时提取出来的可能是ip也有可能是域名,先获取ip $ip=gethostbyname($host_without_protocol); //判断是否是私有ip if(!filter_var($ip,FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE)){ $this->stateInfo=$this->getStateInfo("INVALID_IP"); return; } //获取请求头并检测死链 $heads=get_headers($imgUrl,1); if(!(stristr($heads[0],"200")&&stristr($heads[0],"OK"))){ $this->stateInfo=$this->getStateInfo("ERROR_DEAD_LINK"); return; } //格式验证(扩展名验证和Content-Type验证) if(!isset($heads['Content-Type'])||!stristr($heads['Content-Type'],"image")){ $this->stateInfo=$this->getStateInfo("ERROR_HTTP_CONTENTTYPE"); return; }else{ if(count($this->config['allowFiles'])>0){ $fileType=strtolower(strrchr($imgUrl,'.')); if(strpos($fileType,"?")){ $fileType=strstr($fileType,"?",true); } if(!in_array($fileType,$this->config['allowFiles'])){ //$this->stateInfo=$this->getStateInfo("ERROR_HTTP_ALLOWFILES"); //return; } } } //打开输出缓冲区并获取远程图片 ob_start(); $context=stream_context_create( array('http'=>array( 'follow_location'=>false//don'tfollowredirects )) ); readfile($imgUrl,false,$context); $img=ob_get_contents(); ob_end_clean(); $imgUrl2=$imgUrl; if(strpos($imgUrl,"?")){ $imgUrl2=substr($imgUrl,0,strripos($imgUrl,"?")); } preg_match("/[/]([^/]*)[.]?[^./]*$/",$imgUrl2,$m); $this->oriName=$m?$m[1]:""; if(!strpos($this->oriName,".")){ if(strpos($heads['Content-Type'],'/')){ $this->oriName.=".".substr($heads['Content-Type'],strpos($heads['Content-Type'],'/')+1); }else{ $this->oriName.=".png"; } } $this->fileSize=strlen($img); $this->fileType=$this->getFileExt(); $this->fullName=$this->getFullName(); $this->filePath=$this->getFilePath(); $this->fileName=$this->getFileName(); $dirname=dirname($this->filePath); //检查文件大小是否超出限制 if(!$this->checkSize()){ $this->stateInfo=$this->getStateInfo("ERROR_SIZE_EXCEED"); return; } //创建目录失败 if(!file_exists($dirname)&&!mkdir($dirname,0777,true)){ $this->stateInfo=$this->getStateInfo("ERROR_CREATE_DIR"); return; }elseif(!is_writeable($dirname)){ $this->stateInfo=$this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); return; } //移动文件 if(!(file_put_contents($this->filePath,$img)&&file_exists($this->filePath))){//移动失败 $this->stateInfo=$this->getStateInfo("ERROR_WRITE_CONTENT"); }else{//移动成功 $this->stateInfo=$this->stateMap[0]; } } /** *上传错误检查 *@param$errCode *@returnstring */ privatefunctiongetStateInfo($errCode) { return!$this->stateMap[$errCode]?$this->stateMap["ERROR_UNKNOWN"]:$this->stateMap[$errCode]; } /** *获取文件扩展名 *@returnstring */ privatefunctiongetFileExt() { returnstrtolower(strrchr($this->oriName,'.')); } /** *重命名文件 *@returnstring */ privatefunctiongetFullName() { //替换日期事件 $t=time(); $d=explode('-',date("Y-y-m-d-H-i-s")); $format=$this->config["pathFormat"]; $format=str_replace("{yyyy}",$d[0],$format); $format=str_replace("{yy}",$d[1],$format); $format=str_replace("{mm}",$d[2],$format); $format=str_replace("{dd}",$d[3],$format); $format=str_replace("{hh}",$d[4],$format); $format=str_replace("{ii}",$d[5],$format); $format=str_replace("{ss}",$d[6],$format); $format=str_replace("{time}",$t,$format); //过滤文件名的非法自负,并替换文件名 $oriName=substr($this->oriName,0,strrpos($this->oriName,'.')); $oriName=preg_replace("/[|?"<>/*]+/",'',$oriName); $format=str_replace("{filename}",$oriName,$format); //替换随机字符串 $randNum=rand(1,10000000000).rand(1,10000000000); if(preg_match("/{rand:([d]*)}/i",$format,$matches)){ $format=preg_replace("/{rand:[d]*}/i",substr($randNum,0,$matches[1]),$format); } $ext=$this->getFileExt(); return$format.$ext; } /** *获取文件名 *@returnstring */ privatefunctiongetFileName(){ returnsubstr($this->filePath,strrpos($this->filePath,'/')+1); } /** *获取文件完整路径 *@returnstring */ privatefunctiongetFilePath() { $fullname=$this->fullName; $rootPath=$_SERVER['DOCUMENT_ROOT']; if(substr($fullname,0,1)!='/'){ $fullname='/'.$fullname; } return$rootPath.$fullname; } /** *文件类型检测 *@returnbool */ privatefunctioncheckType() { returnin_array($this->getFileExt(),$this->config["allowFiles"]); } /** *文件大小检测 *@returnbool */ privatefunctioncheckSize() { return$this->fileSize<=($this->config["maxSize"]); } /** *获取当前上传成功文件的各项信息 *@returnarray */ publicfunctiongetFileInfo() { returnarray( "state"=>$this->stateInfo, "url"=>$this->fullName, "title"=>$this->fileName, "original"=>$this->oriName, "type"=>$this->fileType, "size"=>$this->fileSize ); } }
解决的问题:
1、地址后面带参数的问题,获取不到正确的扩展名。
2、地址中不包含扩展名的问题,使用 content-type 过滤,取消文件扩展名的过滤;
3、获取不到正确的扩展名的时候,从 content-type 中获取,content-type 中也没有的话,设置默认的扩展名为 .png
本文地址:https://xzo.com.cn/develop/empire/420.html
如果您认可我们的分享,有意与我们合作开展帝国cms网站建设与开发业务或插件定制,请联系右侧在线客服。我们能给您的,就是高质量的模板与售后。
标注了信息来源为下载鸥的文章皆为原创,如果是转载的优质文章,我们也都标注了出处。如果您喜欢我们的文章,请按照下载鸥所标注的文章出处进行标注,谢谢您的配合。
帝国cms是一款功能极为强大的cms程序,性能强悍、安全性高,可轻松支持10万数据,高级开发人员可制作出能容纳千万数据量的网站,是国内最出色的开源cms程序之一,推荐企业用户使用。
当前最新版本为7.5,8.0版本即将上线,新版本的核心优化点在于多终端的适配。
帝国CMS的信息是绑定内容模板的,通过本教程可以实现在前台自由使用不同的模...
一些颜色比较丰富的站点对模板的样式有要求,例如隔行变色:一行默认色,一行红色...
帝国cms7.5默认是有关键词标红功能的,但一些站使用了二开版本的搜索结果支持...
客户站点由于员工操作失误,直接删除了20篇文章。如果有定期备份,那恢复数据即...
如果平时喜欢挂着帝国cms网站后台不关闭,又留心了网站日志的朋友就会发现DoT...
帝国cms默认是一个账号只能一个人登陆,其他人登陆时之前在线的用户将被挤下...
今天客户遇到一个问题,会员发布投稿信息后白屏了。但信息会正常发布出来,后台...
我们在开发帝国cms登陆模板时经常需要调用会员头像,但帝国CMS默认并没有提供...
在前面的文章中,我们介绍了怎样让MySQL支持emoji表情。但这只是第一步,因为帝...
现在帝国CMS默认广告JS会被浏览器广告插件屏蔽过滤,比如ABP广告过滤插件。...
帝国cms动态页面是不支持默认标签使用的,除非修改一下让动态页面支持标签语...
帝国cms强制https/跳转https的方法...
帝国CMS栏目缓存调用面包屑方法,在userfun.php中加入以下函数,并在模板中使用...
我们首先去看下数据库phome_enewspubtemp是什么表,enewspubtemp为公共模板表...
先查询当前信息ID和栏目ID,在循环出来当前信息的TAGS内容。这里的tags链接用...
帝国CMS赞和踩功能官方默认的方法只能在内容页使用,在列表页怎么使用了,其实...