tp剩余未验证内容-3

为什么有时候会 出现 "上传文件保存错误"?

public function save($file, $replace=true){

        /* 移动文件 */
        if (!move_uploaded_file($file['tmp_name'], $filename)) {
            $this->error = '文件上传保存错误!';    // 比如写权限, 或文件本身的一些问题, 或者 网络关闭/网速慢等的一些问题等
            return false;  // 都有可能 引起上传文件的 保存错误! 
        }
}

说明报 这个错的 原因是: 因为在 将 $file['tmp_name'] 临时文件 移动/剪切到 指定的 保存路径时, 发生了错误.
可以将这个时候的 $file['tmp_name'] 打印出来看看.

也有可能是 move_uploaded_file() 函数有特殊的要求??


===========================

当文件上传成功时, 为什么在 $file你是看不到 tmp_name和 error的?

  • 因为在 public function upload()函数中,调用了 $this ->uploader 的 save() 方法: $this->uploader->save() 而且在 save成功的时候, 就把 这两个 元素给unset了:

  • 在upload上传时, 你要获取错误, 既可以用 Upload类 的 $this->getError(), 也可以用 $this->uploader->getError( 或 $up -> getError() ). 两者其实是一样的, 因为: 在 Upload类的 方法中:

public function getError(){
    return $this->error;
}


 而在 upload方法中, 

    if($this->uploader->save($file, $this->replace)){ // 上传成功时  就把$file中的 tmp_name和 error这两个索引给删除了的, 所以后来就看不到了....
        unset($file['tmp_name'], $file['error'];
        $info[$key] = 
 $file // 二维数组的索引名称 就等于当前遍历的文件名
}else{

        $this->error = $this -> uploader-> getError();  //  Upload类的私有成员error 就是由 上传类实例的getError来的. 所以两者是一样的. 
}
  • 实在 要在 上传错误时, 查看 临时文件名称, 可以在 upload()方法中, 开始就 dump ($files) 或 dump($_FILES). 或者, 在 uploader的save()方法中, 甚至在 调用了$this->uploader->save()方法后, unset之前 都可以用 $file['tmp_name']去查看 上传文件的临时 文件名....

上传时, 明明选择了文件, 却提示" 没有上传的文件"?

这是因为: 当上传的文件超过了 php.ini 设置中的 Post_max_size(默认=8M )时, 表单将不会上传任何信息, 此时的 $_POST & $_FILES 将为 空值.
因此, 正好在 upload方法中, 有: if(empty($file)) { $this->error = '没有上传的文件'; return false; }

在上传的时候, 首先是生成了 $_FILES 数组, 从其名字 就可以看出, 这个是关于 多个上传文件的信息 组成的 二维数组. 这个 $_FILES 时php原生的东西, 跟任何框架, 任何函数方法都没有关系的.

  • 所谓的 upload类等 ,只是对 上传的 原生方法进行了加工和封装, 主要是增加了一些 内部判断 语句, 比如 它的private function check($file) { if(!$this->checkSize($file[
    size'))...; if(!$this->checkExt($file['ext']))...; if(!$this->checkMime($file['mime'])).....}

  • tp 上传类中, $files就等于 $_FILES了, 其中的每一个元素(文件)就是 $file. 最后生成的 信息 时$info. 不能搞混了.

  • 这个数组中 的索引名称就是 上传表单的input的那个name. 然后 元素的值就是关于这个上传到 临时目录的文件的信息组成的数组$file

  • 原生的 $_FILES 中, 每个文件的原数据 其实只有 5个: 即 name, type , tmp_name, error(错误代号, 默认为0, 出错为1) ,size 跟$info记录的不同

  • 上传文件的tmp_name其实是在 c:/wamp/tmp目录中, 默认的临时文件名称是 php(当前上传文件的序号, 按16进制的方式进行 编排的. ).tmp 比如: php10.tmp, c:/wamp/tmp/php10.tmp, php16.tmp php1A.tmp(超过16后就是A开始的了)....等等.

array (size=1)
  'upfile' => 
    array (size=5)
      'name' => string 'foobar.exe' (length=15)
      'type' => string 'application/octet-stream' (length=24)
      'tmp_name' => string 'C:\wamp\tmp\php17.tmp' (length=21)
      'error' => int 0
      'size' => int 3463680

为什么c:/wamp/tmp目录中 没有 上传临时文件? 即使有临时文件, 也不能再使用了?

  • 如果要手动处理 上传文件的话, 步骤是: 原始文件 -> 中间临时 上传到 临时目录 c:/wamp/tmp -> 再由用户来自己按照需要处理

  • 临时目录中的文件通常被 move走了的, 所以没有了.

  • 如果不是move, 而是copy的话, 那么 临时上传文件就一直存在, 当这个脚本执行完毕后(即退出上传过程后), 这个临时文件虽然还存在, 但是不能再被处理了, 因为它
    已经不是一个 is_uploaded_file() 了, 所以, 你用 move_uploaded_file() 来处理的话, 就会报错了.

所以在 上传 封装方法中, 由判断:

        /* 检查是否合法上传 */
        if (!is_uploaded_file($file['tmp_name'])) {
            $this->error = '非法上传文件!';
            return false;
        }

move_uploaded_file()方法的过程?

  • 如同这个函数的名字一样, 它有几个检查的地方, 首先这个文件必须是:经过httppost的方法和机制上传的文件,也就是 is_uploaded_file() 要返回真,
  • 其次, 这个文件, 会 去 上传文件的临时目录c:/wamp/tmp/ 目录中 去查找 $file, 如果找到了 就 "move" 到 新的位置, 注意是move, 所以 临时文件就没有了.

  • 但是 , 并不是 每一次 move_uploaded_file都会成功, 可能会因为 一些原因, 比如: 权限, 比如 文件本身的一些 特殊原因 等等, 可能会使得 这个move 函数 失败, 从而返回false.


最后, 就是 如果 要 避免 上传 保存的文件名, 出现 中文乱码的情况, 上传保存文件最好 就不要使用 中文 名称. 而是使用 纯数字 来命名, 比如:

       $cfg = array(
            'rootPath'  => './Public/',
            'savePath'  => 'Uploads/',
            'saveName'  => time().mt_rand(),  // 这里就是使用 的 直接 "字符串"的方式, 是 用函数拼接字符串. 
        );

即使这里的保存文件名是数字或 其他什么的 数字和字母 任意拼接, 都没有关系! 因为最后,都 要把这个 $info的 信息中的 savename 和原始name 以及其他一些信息都要保持到 数据库中去的.


猜你喜欢

转载自www.cnblogs.com/bkylee/p/9119568.html
tp3