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

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

939 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创建新栏目乱码怎么办?

经常会有用户朋友反馈说新建的栏目页面怎么不对,或者说新建栏目怎么乱码了?总...

15 844
帝国cms列表页怎样置顶?
帝国cms列表页怎样置顶?

在很多时候,我们有信息置顶的需求。但大家在后台信息设置好置顶后可能会发现...

11 935
宝塔面板帝国cms搬家报错No input file specified
宝塔面板帝国cms搬家报错No input file specified

今天有客户向鸥哥求助说宝塔面板帝国cms搬家报错No input file specified,这...

23 2270
帝国CMS怎样在栏目文章列表中间插入一条新数据到指定位置?
帝国CMS怎样在栏目文章列表中间插入一条新数据到指定位置?

有客户的小说站在发布完一篇小说后,发现遗漏了一章。此时如果新增一章必然是...

14 1086
帝国cms怎样将一二三级置顶改为首页栏目置顶等其他名字?
帝国cms怎样将一二三级置顶改为首页栏目置顶等其他名字?

帝国cms推荐、头条级别要改名都可以在栏目设置(栏目-头条/推荐级别)里进行修...

1 574
帝国CMS精准像素美化版怎样修改网站名
帝国CMS精准像素美化版怎样修改网站名

帝国CMS官方默认后台挺难看的,如果自用还可以,给客户则可能让客户怀疑你的审...

1 531
帝国cms面包屑导航[!–newsnav–]修改方式大合集
帝国cms面包屑导航[!–newsnav–]修改方式大合集

本文介绍的帝国cms面包屑导航newsnav修改为newsnav完整的修改攻略,包括标签...

11 2390
帝国CMS提示信息函数printerror()怎么用?
帝国CMS提示信息函数printerror()怎么用?

我们知道js有alert属性可用于弹窗提示,但比较难看。帝国cms的弹窗提示虽然同...

0 548
推荐插件
帝国cms批量添加后台用户插件
帝国cms批量添加后台用户插件

使用帝国cms的企业用户、新闻资讯类站点的用户很多,此类站点很多时候需要有...

0 899
帝国cms多栏目多数据表自动审核推送插件
帝国cms多栏目多数据表自动审核推送插件

本插件基于帝国cms帝国cms每日自动审核插件,在自动审核指定条数信息的基础上...

0 1042
帝国CMS内网用户静态站点文章访客统计插件
帝国CMS内网用户静态站点文章访客统计插件

本插件适用于内网用户,可查看单篇文章访问者ip地址。如果添加访问者ip组,可查...

0 666
帝国cms百度AI图像无损放大api接口对接插件
帝国cms百度AI图像无损放大api接口对接插件

通过本插件,可以实现帝国cms网站对接百度云api实现图像无损放大的功能。经过...

0 551
帝国cms自动生成文章新闻目录插件下载
帝国cms自动生成文章新闻目录插件下载

用户体验是我们的需求,百度蜘蛛的认可更是我们的需求。毕竟,没有收录排名,何来...

0 1264
帝国cms百度AI图像去雾api接口对接插件
帝国cms百度AI图像去雾api接口对接插件

通过本插件,可以实现帝国cms网站对接百度云api实现图像去雾的功能。经过实际...

0 550
帝国cms网站会员登录与退出历史记录日志插件
帝国cms网站会员登录与退出历史记录日志插件

帝国cms默认只有上次登录时间与ip,没有一个记录清单,所以今天,我们分享这个帝...

0 500
帝国cms百度文字识别ocr接口对接插件
帝国cms百度文字识别ocr接口对接插件

许多网站会做一些小功能小插件给客户使用以增强用户黏性,比如图片转文字,这种...

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