php上传

来源:互联网 发布:nginx deny 编辑:程序博客网 时间:2024/06/05 20:17
 

1、  全局变量$_FILES[‘xxx’];

    PHP5新创了一个$_$_FILES全局变量来接收文件的上传。这和以往版本有些差别。在旧版本里,你可以打开register_globals=on直接使用全局变量,或使用$HTTP_POST_FILSE[‘xxx’],这里只研究PHP5

 

2文件上传表单

    1,上传文件的表单使用post方式(和get的区别不用说了);还要加上enctype='multipart/form-data'。
    2,一般要加上隐藏域:

<input type=hidden name='MAX_FILE_SIZE' value=”30000”>,位置在file域前面。value的值是上传文件的客户端字节限制。据说可以减少文件超标时客户端的等待时间,不过我没觉得有什么区别。
   注意:MAX_FILE_SIZE 的值只是对浏览器的一个建议,实际上它可以被简单的绕过。因此不要把对浏览器的限制寄希望于该值。实际上,PHP.ini 设置中的上传文件最大值,是不会失效的。但是最好还是在表单中加上 MAX_FILE_SIZE,因为它可以避免用户在花时间等待上传大文件之后才发现该文件太大了的麻烦

    3,出于安全考虑,file域是不许赋值的。随便在file域输入字符串,然后按submit也不会有反应。必须是第二个字符是冒号的时候(比如空格跟随冒号可以上传一个长度为0字节的“文件”),submit才同意“服务”——不过这个是客户端的措施,跟MAX_FILE_SIZE一样很容易绕过去。

 

Page1.php:

<form enctype="multipart/form-data" action="page2.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="8388608">
上传文件: <input name="userfile" type="file">
<input type="submit" value="提交">
</form> 

3、上传8M以下文件如何设置php.ini;

 

打开php.ini,首先找到
File Uploads区域

有影响文件上传的以下几个参数:
file_uploads = on ;是否允许通过HTTP上传文件的开关。默认为ON即是开
upload_tmp_dir ;文件上传至服务器上存储临时文件的地方,如果没指定就会用系统默认的临时文件夹
upload_max_filesize = 8388608 ;望文生意,即允许上传文件大小的最大值。默认为2M,必须换算成byte单位:1M=1024K;1K=1024byte

Data Handling ;区域

还有一项:post_max_size = 8m ;指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值。默认为8M
一般地,设置好上述四个参数后,在网络正常的情况下,上传<=8M的文件是不成问题。

 

4、 上传大于8M文件如何设置php.ini;

 

如果要上传>8M的大体积文件,只设置上述四项还一定能行的通。除非你的网络真有100M/S的上传高速,否则你还得关心关心下面的参数:

Resource Limits
max_execution_time = 600 ;每个PHP页面运行的最大时间值(秒),默认30秒
max_input_time = 600 ;每个PHP页面接收数据所需的最大时间,默认60秒
memory_limit = 8m ;每个PHP页面所吃掉的最大内存,默认8M
把上述参数修改后,在网络所允许的正常情况下,就可以上传大体积文件了。

好了,设置好现在就可以一试。点击一个200大M的文件上传一下,在你听歌、想MM或上厕所回来过程中,程序会告诉你上传成功啦~在本机上测试上传200M的文件成功。

另外,据说上传大文件最好用FTP方法,我对PHP的FTP不太熟,这里就不研究了。

 

5、 文件上传错误代码

 预定义变量$_FILES数组有5个内容:
    $_FILES['userfile']['name']——客户端机器文件的原名称

    $_FILES['userfile']['type']——文件的 MIME 类型

    $_FILES['userfile']['size']——已上传文件的大小,单位为字节

    $_FILES['userfile']['tmp_name']——文件被上传后在服务端储存的临时文件名

    $_FILES['userfile']['error']——和该文件上传相关的错误代码


其中$_FILES['userfile']['error']的可以有下列取值和意义:
    0——没有错误发生,文件上传成功。
 
    1——上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
 
    2——上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
 
    3——文件只有部分被上传。
 
    4——没有文件被上传。

 

1~3不用说了。“没有文件被上传”(4)是指表单的file域没有内容,是空字符串。
    “文件上传成功”(0)不一定真的有文件上传了。比如你打了个“c:”给file域,就可以“上传成功”——错误代码是0,['name']是“c:”,['type']是“application/octet-stream”,['size']是0,['tmp_name']是“xxx.tmp”(xxx是服务器起的名字)

 

这里我有个小发现,起初使用PHP5.14时,无论page1.php里面<input name="userfile"
type="file">的name等于什么,在上传处理脚本中都只能用$_FILES['userfile']来接收;

后来改用PHP5.16,发现$_FILES['userfile']必须和<input name="userfile" type="file">命名相对应了。比如name=”book”,则处理脚本必须用$_FILES['book']来接收。请大家注意一下自己的版本号。

 

6、上传文件大小限制
    限制上传文件大小的因素有
    1,客户端限制:隐藏域MAX_FILE_SIZE的数值(可以被绕开)。

    2,服务器端限制:upload_max_filesize,post_max_size和memory_limit。这几项不能够用脚本来设置,也可以在php.ini里设置,参考本文3、4条。

    3,自定义限制。

7、上传文件格式检验

    1、检验文件格式的方法应该很多,可以检测MIME类型,也可以用正则表达式判断,这里推
    荐一种我常用的:

        //自定义允许的文件上传格式;

        $upload_type=".jpeg,.png,.gif,.rar,.zip,.chm,.html,.htm";

        //检验上传文件是否符合格式的函数。

        function check_type($upload_type){

            $file_name=$_FILES['$form']['name'];

            $findtype=strtolower(strrchr($file_name,"."));

            $allow=strpos($upload_type,$findtype);

            if($allow===false){

                echo"文件格式不符";

                exit;

            }

        }

    2、  关于通过$_FILES['userfile']['type']——文件MIME类型来检查上传格式,有必要对MIME进行一些讨论。

   什么是MIME?(不必深入了解,粗知大略即可)
    MIME表示多用途Internet邮件扩允协议。MIME扩允了基本的面向文本的Internet邮件系统,以便可以在消息中包含二进制附件

 

RFC822在消息体的内容中做了一点限制:就是只能使用简单的ASCII文本。所以,MIME信息由正常的Internet文本邮件组成,文本邮件拥有一些特别的符合RFC822的信息头和格式化过的信息体(用ASCII的子集来表示的附件)。这些MIME头给出了一种在邮件中表示附件的特别的方法。

MIME信息包含了哪些东西?

一个普通的文本邮件的信息包含一个头部分(To: From: Subject: 等等)和一个体部分(Hello Mr.,等等)。在一个符合MIME的信息中,邮件的各个部分叫做MIME段,每段前也缀以一个特别的头。MIME邮件只是基于RFC 822邮件的一个扩展。然而它有着自已的RFC规范集。

头字段

MIME头根据在邮件包中的位置,大体上分为MIME信息头和MIME段头,MIME信息头指整个邮件的头,而MIME段头只每个MIME段的头。

MIME信息头有:

MIME-Version:
这个头提供了所用MIME的版本号。这个值习惯上为1.0。

Content-Type:
它定义了数据的类型,以便数据能被适当的处理。有效的类型有:text,image, audio,video,applications,multipart和message。注意任何一个二进制附件都应该被叫做application/octet-stream。这个头的一些用例为:image/jpg, application/mswork,multipart/mixed 。

Content-Transfer-Encoding:
它说明了对数据所执行的编码方式,客户/MUA将用它对附件进行解码。对于每个附件,可以使用7bit,8bit,binary ,quoted-printable,base64和custom中的一种编码方式。7bit编码是用在US ASCII字符集上的常用的一种编码方式。8bit 和binary编码一般不用。对可读的标准文本,如果传输要经过对格式有影响的网关时对其进行保护,可以使用quoted printable 。Base64是一种通用方法,在需要决定使用哪一种编码方法时,它提供了一个不用费脑子的选择;它通常用在二进制,非文本数据上。注意,任何非7bit 数据必须用一种模式编码,这样它就可以通过Internet邮件网关。

Content-ID:
如果Content-Type是message/external-body或multipart/alternative时,这个头就有用了。

Content-Descrīption:
这是一个可选的头。它是任何信息段内容的自由文本描述。描述必须使用us-ascii码。

Content-Disposition:
这是一个试验性的头,它用于给客户程序/MUA提供提示,来决定是否在行内显示附件或作为单独的附件。

 

当然,在使用PHP检查上传格式时,没有必要把MIME搞得那么复杂,对那些高深的理论,粗知大略就可以了。倘若我们要上传ZIP和RAR的文件,你可以在接收文件的php中写上:
      $filetype=$_FILES['userfile']['type'];
     echo"$filetype";
    
就可看到上传文件的mime类型.
     ZIP
MIME类型用application/x-zip-compressed
     RAR
MIME类型用application/octet-stream

然后再用如下代码判断格式:

switch ($_FILES['userfile']['type']) {
case "application/x-zip-compressed":
break;
case "application/octet-stream":
break;
case "text/plain":
break;
default:
print "您上传的文件类型不对";
exit(0);
break;
}

 

个人认为上传文件最好的办法使用一个功能齐全的类,自己写的话太麻烦了。PHP的竞争对手ASP.NET都把文件上传,广告轮显等功能做成组件了,可视化操作,瞧得让人眼热——当然,眼热归眼热,我还是会极力克制自己不去学的。理由很简单,无论是ASP.NET,PHP还是JSP,其作用都是做网站。既然作用都一样,那么好比杀猪,用剔骨尖刀是杀猪,用太极剑法是杀猪,即使你聪明英俊才华盖世玉树临风,精通太极剑,剔骨刀,宰牛刀三种武艺来杀猪,其结果也只有一个——猪被杀死了;那么,我宁肯只学一刀,只精通一刀,我也能把猪杀的很不错。有那么多时间、那么多精力去重复学习一些作用相同的技术,倒不如学点别的,比如为人处事,经营管理,或者琢磨一下如何追MM,以解决程序员找对象老大难的问题等。

PHP对组件的支持非常不好,这是它的一个缺点。但传说Zend公司许诺明年将发布Zendbox,大力支持组件,也不知效果如何。Zend今年给我们太多的承诺了,说明年这也发布那也发布……强力期盼中……

 

8、开始上传文件

//上接page1.php,这里为了说明原理,省略了对上传文件格式、大小的判断。

Page2.php

<?php

// 在 4.1.0 以前的 PHP 中,需要用 $HTTP_POST_FILES 代替 $_FILES。

// 在 4.0.3 以前的 PHP 中,需要用 copy()来代替 move_uploaded_file()。

 

//上传文件的路径,这里是基于linux的,如有需要请自行修改。

$uploaddir = '/var/www/uploads/';

$uploadfile = $uploaddir. $_FILES['userfile']['name'];

print "<pre>";

if (is_uploaded_file($_FILES['userfile'])) {

if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {

    print "文件上传成功:/n";

    print_r($_FILES);

} else {

    print "文件上传失败:/n";

    print_r($_FILES);

}

}

print "</pre>";

?>

is_uploaded_file():该函数用来判断文件到底是客户端上传的呢还是本机原有的。传说中国外有个软件,它可以迷惑服务器,并使其误把本机文件当成是客户端上传的。这就很危险了:如果在linux服务器下,不法分子把包含root密码的敏感文件窃而走之,你的主机就马上变肉鸡,任人宰割了。

move_uploaded_file()把客户端上传的文件从临时文件里移走。和copy相比,该函数显得安全多了。它只移走客户端上传的文件;至于移动本机文件,还是用copy吧.

 

9、下面演示一个简单的文件上传例子(20M25M):

Php.ini设定:

post_max_size=23068672

file_uploads = On

upload_max_filesize=26214400

max_execution_time = 600
max_input_time = 600
memory_limit = 10M  

设定完记得重启apacheIIS

 

Page1.php:

<form enctype="multipart/form-data" action="page2.php" method="POST">

<input type="hidden" name="MAX_FILE_SIZE" value="8388608">

上传文件: <input name="myup" type="file">

<input type="submit" value="提交">

</form>

Page2.php

<html>

<head>

<title>文件上传</title>

10、一个简单的文件上传类:

这个类很简单的,功能并不齐全;其实也是从phpchina找到的。本人学习文件上传的方法就是:在phpchina搜索相关的帖子,全部保存下来,然后潜行研究,务求精熟,这样你会发现很多书本上没有的知识,如果不嫌我的办法笨的话,phper朋友们可以试试。

     class upload{

          public $formname="userfile";//表单元素file的名字;

          public $upload_path="upload/";//上传文件的保存路径;

          public $upload_file_size="10485760";//允许上传文件的大小;

          public $upload_type=".jpeg,.png,.gif,.rar,.zip,.chm,.html,.htm";

         

          function __construct($formname1="userfile",$upload_file_size1="10485760",$upload_path1="upload/",$upload_type1=".jpeg,.png,.gif,.rar,.zip,.chm,.html,.htm"){

                $this->upload_false();

          }

          //少数浏览器支持PUT方法而不支持POST,可以据check_method()函数检验;

          function check_method(){

                 if($_SERVER['REQUEST_METHOD']!='POST'){

                  echo"对不起,您的浏览器不支持POST方法上传,如要继续使用本站,请使用IE或Firefox浏览器!";

                  exit;

            }

          }

          //检查文件格式是否符合规定;

          function check_type($upload_type1){

                 $form=$this->formname;

            $file_name=$_FILES['$form']['name'];

            $findtype=strtolower(strrchr($file_name,"."));

            $allow=strpos($upload_type,$findtype);

            if($allow===false){

                   echo"文件格式不符";

                   exit;

            }

          }

          //检验是否从本地上传文件;

          function startup(){

                 if(!is_uploaded_file($_FILES[$this->formname]['name'])){

                        echo "不允许从服务器端向服务器端上传文件!";

                        exit;

                 }

                 $path=$this->upload_path;

                 $filename=$path."/".$_FILES[$this->formname]['name'];

                 if(!move_uploaded_file($_FILES[$this->formname]['tmp_name'],$filename)){

                        echo "文件无法移动,上传失败!";

                        exit;

                 }

                 echo "文件上传成功!";

          }

          function upload_false(){

                 $the_error=$_FILES[$this->formname]['error'];

                 switch ($the_error){

                        case 0:echo "文件上传成功!";break;

                        case 1:echo "上传文件的大小超出规定!";break;

                        case 2:echo "上传文件的大小超过了MAX_FILE_SIZE的指定值!";break;

                        case 3:echo "文件只有部分被上传!";break;

                        case 4:echo "文件没有被上传!";break;

                 }

                 $this->startup();

                 $this->check_type();

                 $this->check_method();

          }

     }

原创粉丝点击