下载鸥 > 网站下载 > 开发教程 > 帝国CMS

帝国cms默认编辑器UEdito读取远程图片失效

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("&amp;","&",$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

有帮助,很赞!

信息来源:精准像素
导出教程 下载word版教程
发表评论 共有条评论
关于帝国CMS


帝国cms是一款功能极为强大的cms程序,性能强悍、安全性高,可轻松支持10万数据,高级开发人员可制作出能容纳千万数据量的网站,是国内最出色的开源cms程序之一,推荐企业用户使用

当前最新版本为7.5,8.0版本即将上线,新版本的核心优化点在于多终端的适配。

推荐帝国CMS开发教程
帝国CMS怎样让一条信息具有多个模板?
帝国CMS怎样让一条信息具有多个模板?

帝国CMS的信息是绑定内容模板的,通过本教程可以实现在前台自由使用不同的模...

17 495
帝国CMS怎样做隔行变色的功能?
帝国CMS怎样做隔行变色的功能?

一些颜色比较丰富的站点对模板的样式有要求,例如隔行变色:一行默认色,一行红色...

16 560
帝国cms搜索结果关键词标红怎么实现?
帝国cms搜索结果关键词标红怎么实现?

帝国cms7.5默认是有关键词标红功能的,但一些站使用了二开版本的搜索结果支持...

3 325
帝国cms误删了已收录的文章要怎么恢复数据?
帝国cms误删了已收录的文章要怎么恢复数据?

客户站点由于员工操作失误,直接删除了20篇文章。如果有定期备份,那恢复数据即...

0 353
帝国cms后台DoTimeRepage.php一直刷新写满日志了怎么办?
帝国cms后台DoTimeRepage.php一直刷新写满日志了怎么办?

如果平时喜欢挂着帝国cms网站后台不关闭,又留心了网站日志的朋友就会发现DoT...

1 490
帝国cms后台取消单个账号不允许同时在线
帝国cms后台取消单个账号不允许同时在线

帝国cms默认是一个账号只能一个人登陆,其他人登陆时之前在线的用户将被挤下...

3 1154
帝国cms会员投稿后白屏怎么办?
帝国cms会员投稿后白屏怎么办?

今天客户遇到一个问题,会员发布投稿信息后白屏了。但信息会正常发布出来,后台...

1 308
帝国CMS在JS调用登陆模板中调用会员头像
帝国CMS在JS调用登陆模板中调用会员头像

我们在开发帝国cms登陆模板时经常需要调用会员头像,但帝国CMS默认并没有提供...

0 295
随机帝国CMS开发教程
帝国cms怎样才能支持emoji表情?
帝国cms怎样才能支持emoji表情?

在前面的文章中,我们介绍了怎样让MySQL支持emoji表情。但这只是第一步,因为帝...

8 749
帝国CMS默认广告JS被屏蔽过滤解决方法
帝国CMS默认广告JS被屏蔽过滤解决方法

现在帝国CMS默认广告JS会被浏览器广告插件屏蔽过滤,比如ABP广告过滤插件。...

3 328
帝国cms动态页面调用栏目导航
帝国cms动态页面调用栏目导航

帝国cms动态页面是不支持默认标签使用的,除非修改一下让动态页面支持标签语...

7 788
帝国cms强制https / 跳转https的方法
帝国cms强制https / 跳转https的方法

帝国cms强制https/跳转https的方法...

11 762
帝国CMS栏目缓存调用面包屑方法
帝国CMS栏目缓存调用面包屑方法

帝国CMS栏目缓存调用面包屑方法,在userfun.php中加入以下函数,并在模板中使用...

0 752
Table 'XX.***_enewspubtemp_2' doesn't exist错误详解
Table 'XX.***_enewspubtemp_2' doesn't exist错误详解

我们首先去看下数据库phome_enewspubtemp是什么表,enewspubtemp为公共模板表...

3 747
列表页调用当前信息TAGS标签
列表页调用当前信息TAGS标签

先查询当前信息ID和栏目ID,在循环出来当前信息的TAGS内容。这里的tags链接用...

8 814
帝国CMS列表页调用赞和踩功能
帝国CMS列表页调用赞和踩功能

帝国CMS赞和踩功能官方默认的方法只能在内容页使用,在列表页怎么使用了,其实...

0 739
客服QQ:341553759
点击咨询 常见问题 >
官方交流群:90432500
点击加入