欢迎访问融科网络!我们专注于郑州网站建设郑州网站制作郑州网站设计郑州做网站等相关服务!
营销之道 干货分享
了解企业新动态,分享前沿的营销推广干货,成长路上,我们携手同行

编程代码

织梦CMS文件上传功能分析教程

标签: 作者:融科网络 | 点击:
02

Nov
2019

导语
织梦CMS系统里面的上传功能比较多,例如有友情连接里的标志上传、模块管理里面的上传模块和模块打包、发布新图集里面的上传图片集、发布新软件里的上传本地文件、附件管理里
 

织梦CMS系统里面的上传功能比较多,例如有友情连接里的标志上传、模块管理里面的上传模块和模块打包、发布新图集里面的上传图片集、发布新软件里的上传本地文件、附件管理里面的上传新文件、文件式管理器里面的文件上传、织梦会员中心里面的软件上传和缩略图等等,在织梦里面的文件上传功能到处都有应用。

  我们分析三个有代表性的,一个是标志上传,这个是一般的应用,但相对复杂一点;另一个是附件管理时面的上传新文件,这二个一个共同特点是上传的文件都要保存到数据库里面,第三个是文件式管理器里面的文件上传功能,这个与我们之前的教程“php文件(单文件和多文件)上传详解教程”讲的一样,都是简单的上传文件,没有用到数据库知识,我们就以这三个为例子,其它的上传跟这三个可以说大同小异。

  要分析这三个文件让传功能,需要对织梦CMS文件上传处理方式,织梦与我们在php文件(单文件和多文件)上传详解教程里看到的文件上传是很不一样的,毕竟,织梦系统是一比较成熟的cms系统,织梦处理文件上传,不像我们看的教程一样写一个文件就可以了,因为,织梦系统里面用到的文件上传很多,不光是织梦系统,其它系统一定会用到文件上传,只要是网站就会用到文件上传功能。

  织梦是怎么处理文件上传的呢?要了解这个我们就要分析一下文件上传的共同点,然后,把这公共部分放在一个文件,然后,其它上传文件就直接引用这个文件就可以了,这样其它每个上传功能如标志上传,图片集上传,软件上传等各自写适合自己的代码,然后,再引用公共部分即可。这种思想正是函数产生的思想,什么是函数简单而言之,就是把公共功能写成一段代码,其它,需要这个功能时直接调用,而本篇讲的文件调用也正是如此。

  织梦CMS文件上传公共部分在根目录(这就是根目录,如果你在本地的话根目录就是)/include/uploadsafe.inc.php,对就在uploadsafe.inc.php文件里面,这个引用文件功能是:“转换上传的文件相关的变量及安全处理、并引用前台通用的上传函数。”。

  织梦是怎么把这个文件配置到要引用它的文件里的呢?首页,要在/include/common.inc.php里面,写一句如下代码:

if($_FILES)
{
    require_once(DEDEINC.'/uploadsafe.inc.php');
}

  这段代码的意思就是,当要上传文件时,就引用文件uploadsafe.inc.php,如果我们打开例如标志上传文件friendlink.add.php你会发现,没有这个uploadsafe.inc.php文件,是的,织梦还配置了一个在根目录/dede/里面的config.php文件,这个是后台根目录/dede/所有php文件共有的,如果你随便打开个文件,你会发现都引用了这个文件,这个config.php不仅仅包括了上传文件,还包括了数据库连接等很多织梦程序所必备的内容。为什么这样包涵来包涵去?还是为了开发方便,试想如果我们把这些文件里的东西都写进friendlink.add.php里面,那文件得多大啊,更重要的是重复写相同的内容,不利于开发。

  我们就拿标志上传为例子这些文件是这样相互包括的:friendlink.add.php 引入config.php,config.php引入common.inc.php,common.inc.php引入uploadsafe.inc.php。这样无论friendlink.add.php怎么改变都不影响后面的文件,有利于开发。

  现在我们就要分析一uploadsafe.inc.php是怎么转换上传的文件变量即$_FILES及安全设置的。

  打开uploadsafe.inc.php文件,找到foreach($_FILES as $_key=>$_value)这句,这句前面是设置强制哪些文件类型可以上传,并设置了一个数组$keyarr = array('name', 'type', 'tmp_name', 'size');数组$keyarr值正是$_FILES的键,这是为后面进行数组遍历作准备。还对是不是通过编辑器上传作了判断。

  在foreach($_FILES as $_key=>$_value)后面是重点了,通过foreach($_FILES as $_key=>$_value)我们可以得到$_key,这个$_key正是我们表单里面的类型为file的name属性值,这一点特别重要。这句foreach($_FILES as $_key=>$_value)代码就是为了得到这个$_key。为了进一步说明这个$_key我们把$_FILES数组存储的内容分析一下,这里以单个文件上传为例子,多个文件一样。$_FILES存储的内容如下。

  Array
(
    [upmyfile] => Array
        (
            [name] => 1440x900wolf.jpg
            [type] => image/jpeg
            [tmp_name] => D:\APMServ5.2.6\tmp\uploadtemp\php6B1.tmp
            [error] => 0
            [size] => 160666
        )

)

  这句代码foreach($_FILES as $_key=>$_value),正是为了获得这个$_key就是$_FILES里面的upmyfile。接下来我们就要得到name,type,tmp_name,error,size了,我们完全可以再遍历一下$_value,因为$_value又是一个数组,包括这些内容,但是大家想一下,这只是单文件上传,如果是一个多文件上传,是不是比较重杂?是的,织梦想到了一好方案就是先定义一个$Keyarr数组,直接从这个数组里面获取name,type,tmp_name,error,size,既简单,又方快速。

  代码foreach($keyarr as $k)这句正是为了获取name,type,tmp_name,error,size内容。

  接下来这句代码$$_key = $_FILES[$_key]['tmp_name'];是这个uploadsafe.inc.php里面的重中之重,这个代码的等价于$upmyfile = D:\APMServ5.2.6\tmp\uploadtemp\php6B1.tmp;以后,我们在引用uploadsafe.inc.php这个文件的文件里看到类似$upmyfile就等于是$_FILES[$_key]['tmp_name']即上传文件临时文件名,同理

  ${$_key.'_name'} = $_FILES[$_key]['name'] 等价于 $upmyfile_name = $_FILES[$_key]['name'] = 1440x900wolf.jpg。

  ${$_key.'_type'} = $_FILES[$_key]['type'] 等价于 $upmyfile_type = $_FILES[$_key]['type'] = image/jpeg。

  ${$_key.'_size'} = $_FILES[$_key]['size'] 等价于 $upmyfile_size = $_FILES[$_key]['size'] = 160666。

  之所以通过以上方式处理,就是为了在引用uploadsafe.inc.php文件的文件里面,不出现类似$_FILES[$_key]['size']这样长的代码。

  后面的代码就是对文件上传的文件名是不是空,是不是我们允许的文件后缀,文件名是不是少个点进行判断;对文件大小是不是0,如果是我们通过系统函数filesize()获取,如果更加详细的判断还要判断一下,用户上传的内容是不是超出了我们设置的大小,是不是超出了服务器设置的大小,但织梦没有判断在上一个教程“php文件(单文件和多文件)上传详解教程”我们已经作了详细判断。

  最后,对上传的文件类型进行判断,强制使用我们设置的文件类型。

  总结:uploadsafe.inc.php用到的系统函数有是否存在函数etmpty(),通过正则来判断是否匹配preg_match(),检查数组中是否存在某个值in_array(),将字符串转化为小写strtolower(),去除字符串首尾处的空白字符(或者其他字符)trim(),preg_replace — 执行一个正则表达式的搜索和替换等函数,现在我们对uploadsafe.inc.php这个文件已经分析完了。

  一、标志文件上传如下图所示。

织梦CMS文件上传功能分析教程



  现在我们分析以上传标志文件,标志上传处理文件是friendlink.add.php,对应的源码文件是friendlink.add.htm源码文件我们就不用多说了,都是一些html代码,我们只要找到源码中这二句(简化后):

  网站Logo: <input name="标志" type="text" id="标志"/>
   
  上传Logo: <input name="标志img" type="file" id="标志img" />

  我们打开friendlink.add.php文件,程序首先用if(is_uploaded_file($标志img))判断一下上传的文件是不是通过http post上传的?如果是说明是通过本地上传的标志,也就是上面的<input name="标志img" type="file" id="标志img" />这个选择框上传的,如果不是则是通过<input name="标志" type="text" id="标志"/>,直接在这个文件框写上的标志地址。

  若if(is_uploaded_file($标志img))成立则程序向下执行,注意这句代码里面的$标志img指什么?正常的文件框的话,当然是通过$_POLST获得的,例如上面二行中的网站Logo:就是通过$_POST获取值,而上传标志即$标志img则不是通过$_POST获得,而是通过$_FILES获得的,也就是我们在uploadsafe.inc.php里面分析的$upmyfile = D:\APMServ5.2.6\tmp\uploadtemp\php6B1.tmp,只不过现在的$upmyfile变成了$标志img即,$标志img = D:\APMServ5.2.6\tmp\uploadtemp\php6B1.tmp。

  如果你看明白了这点,那么,下面的$标志img_name、$标志img_type、$标志img_size分别对应上传文件的文件名、上传文件的类型、上传文件的大小了。那下面的代码就比较容易了,这是难点也是重点。

  代码$names = split("\.", $标志img_name);意思是把上传的文件名通过正则匹配,模式是通过点分成二部分,存放在数组$name中。

  我给织梦挑一个不算错误:函数preg_split()比split()快,而explode()在这三个中运行速度最快,前二个需要正则表达式,最后这个explode()则使用字符串分割。他们三个都返回数组,所以,这里应当换上explode()最好了,我们做个测试一下,看看返回结果。

   $name = "1440x900wolf.jpg";
 $a = split("\.", $name);
 $b = split("\.", $name);
 $c = explode(".",$name);

 print_r($a);

 echo "<br />";

 print_r($b);

 echo "<br />";

 print_r($c);

  这段代码返回的结果是:

Array ( [0] => 1440x900wolf [1] => jpg )
Array ( [0] => 1440x900wolf [1] => jpg )
Array ( [0] => 1440x900wolf [1] => jpg )

  这充分说明了返回的结果是一样的,所以,建议大家能用explode()就用这个。

  回到friendlink.add.php文件里,$shortname = ".".$names[count($names)-1];这句里面的$names[count($names)-1]获取文件类型名,例如上面的例子jpg。整句就得到了.jpg。

  下面这个判断语句用来判断,我们上传的文件名是不是我们允许的,是不是jpg,gif,png,若不是则直接改后缀名为.gif。
    if(!preg_match("#(jpg|gif|png)$#", $shortname))
        {
            $shortname = '.gif';
        }

  下面这句,是对文件名进行重新命名,这样是为了防止,不同的用户上传相同的名子后,前面的会被后面的覆盖掉。

  $filename = MyDate("ymdHis", time()).mt_rand(1000,9999).$shortname;

  下面这句是设置文件上传路径,其中$cfg_medias_dir附件上传路径,在common.inc.php已经定义。

  $imgurl = $cfg_medias_dir."/flink";

  下面这句判断是不是目录,不是则建立,其中$cfg_basedir是根目录,$cfg_dir_purview是权限,在common.inc.php已经定义。

          if(!is_dir($cfg_basedir.$imgurl))
        {
            MkdirAll($cfg_basedir.$imgurl, $cfg_dir_purview);
            CloseFtp();
        }

  下面这句是要把临时文件转移到对应路径和文件名。

  $imgurl = $imgurl."/".$filename;

  移动文件:下面这个函数是重点,我们上面所做的工作完全就是为这个文件转移函数服务的。

   move_uploaded_file($标志img,$cfg_basedir.$imgurl)
 
  删除临时文件@unlink($标志img);@这个抑制符意思是不显示错误。

      //强制检测用户友链分类是否数据结构不符
    if(empty($typeid) || preg_match("#[^0-9]#", $typeid))
    {
        $typeid = 0;
        $dsql->ExecuteNoneQuery("ALTER TABLE `dede_flinktype` CHANGE `ID` `id` MEDIUMINT( 8 ) UNSIGNED DEFAULT NULL AUTO_INCREMENT; ");
    }
 
  这句看似不重要,实际上这句特别重要,如果这个$typeid错误,直接导致,标志出问题。

  现在就要把友链添加到数据库了,请注意我们上传的标志是把路径保存到数据库里面的,而不是把图片保存到数据库里面,有没有把图片保存到数据库里面的?有,以前听老师讲课时,讲到过,但是极少,一般都是保存图片路径的,这样程序只需要查询一下数据库就知道图片在哪里了,目前,本人从没有见过图片保存到数据库里的。

  目前为止,我们已经把标志上传分析完了。


  二、附件管理——>上传文件如下图所示。

织梦CMS文件上传功能分析教程


  与标志文件上传功能相比,这个文件上传功能需要标题,附加参数,还有一个最大的不同就是,这个功能可以批量上传文件,而且不仅仅是图片,还有flash,音频/视频等。多文件上传,与单文件上传没有多大区别,只不过在单文件上

传的基础上曾加个循环而已。

  重点看这三句代码

  $filesize = ${"upfile".$i."_size"};
  $upfile_type = ${"upfile".$i."_type"};
  $upfile_name = ${"upfile".$i."_name"};

  这不正是我们在upoadsafe.inc.php里面重点分析的吗,在上传标志功能里我们也作了分析,这里不再作过多分析。从代码for($i=0; $i<=40; $i++)开里,当条件if(isset(${"upfile".$i}) && is_uploaded_file(${"upfile".$i}))成立,即已经上传了文件并且是通过http post上传的,那么,程序就判断上传文件类型在不在我们前面定义的二个数组$sparr_image,$sparr_flash里面,如果在则设置存储路径$savePath,若不存在就建立路径,若是非flash类型则打上水印,接下来没有问题,就把数据插入到数据库表dede_uploads,在这个处理程序中用到了取得图像大小的函数getImagesize(),这个函数,不仅可以获得图像的大小,还有高、宽、字节大小、mime类型,为什么要用这个函数?
因为,我们后面的保存数据到数据库表时,要保存高和宽。

  三、文件式管理器 ——>上传文件分析如下图所示。

织梦CMS文件上传功能分析教程



  文件file_manage_control.php就是对上传的文件进行处理的程序,这个更简单,既不用把上传的文件路径插入到数据库,也不用作过多的判断,代码特别简单。它与标志相比多了多个文件上传,与附件管理文上传,少了不需要保存路径,连上传的文件名都不用改,直接用if(!file_exists($cfg_basedir.$activepath."/".$upfile_name))来判断是不是上传的文件名与已经有的文件名重名,结束。

  总结:我们总结一下,如果让我们自己开发一个上传文件功能,怎么开发?

  开发上传文件程序步骤:

   1.设置限制文件类型,一般用数组来设定。
 
   2.判断文件大小,判断错误友好提示信息。

   3.处理$_FILES文件里面的内容,像织梦那样专门做个程序文件upoadsafe.inc.php。

   4.用函数is_uploaded_file()判断上传的临时文件是不是存在,存放则移动文件,用到的函数是move_uploaded_file()。

   5.若要保存到数据库,则插入数据库表。

   6.多个文件处理,这个要用到js,或jquery。使上传效果更酷。 郑州融科网络专注于企业网站建设、网站制作、高端网站设计,郑州荥阳、上街做网站就找融科网络!
本文章网址:http://www.ppssdd.com/code/13862.html。转载请保留出处,谢谢合作!

全网(营销型+响应式)专业定制

快速搭建高询盘+营销独立站

微信扫一扫 添加微信

推荐分享,免费SEO诊断

扫码加好友,即送价值1880元的SEO优化教程

(网站没排名,轻松让关键词上首页!专注H5企业建站+网站优化推广)

上一篇:织梦58教你怎么使用织梦CMS小助手

下一篇:怎么修改"DEDECMS 提示信息!"办法!

  • 网站建设咨询
  • 网站建设案例
建站流程
  • 网站需
    求分析
  • 网站策
    划方案
  • 页面风
    格设计
  • 程序设
    计研发
  • 资料录
    入优化
  • 确认交
    付使用
  • 后续跟
    踪服务
  • 151-3895-5886
  • 品牌网站建设定制
  • 营销型网站建设定制