thinkphp5.1 批量上传文件-生成重复文件名的问题

导读

今天使用了 thinkphp 的图片批量上传发现 同时上传三个文件的状况下 只存储了两个文件缺失一个文件,调试发现 生成文件名时 生成出一样的名字致使文件被覆盖.php

官方文档示例-多文件上传

  • 视图thinkphp

    <form action="/index/index/upload" enctype="multipart/form-data" method="post">
      <input type="file" name="image[]" /> <br> 
      <input type="file" name="image[]" /> <br> 
      <input type="file" name="image[]" /> <br> 
      <input type="submit" value="上传" /> 
      </form>
    复制代码
  • 控制器框架

    public function upload(){
       // 获取表单上传文件
          $files = request()->file('image');
          foreach($files as $file){
          // 移动到框架应用根目录/uploads/ 目录下
          $info = $file->move( '../uploads');
          if($info){
              // 成功上传后 获取上传信息
              // 输出 jpg
              echo $info->getExtension(); 
              // 输出 42a79759f284b767dfcb2a0197904287.jpg
              echo $info->getFilename(); 
          }else{
              // 上传失败获取错误信息
              echo $file->getError();
          }    
      }
    复制代码

    }函数

上述代码在move 过程当中直接生成了文件名 , 看下是怎么生成文件名的post

  • /thinkphp/library/think/File.php 自动 生成文件名的方法是autoBuildNameui

    protected function autoBuildName()
      {
          if ($this->rule instanceof \Closure) {
              $savename = call_user_func_array($this->rule, [$this]);
          } else {
              switch ($this->rule) {
                  case 'date':
                      $savename = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true));
                      break;
                  default:
                      if (in_array($this->rule, hash_algos())) {
                          $hash     = $this->hash($this->rule);
                          $savename = substr($hash, 0, 2) . DIRECTORY_SEPARATOR . substr($hash, 2);
                      } elseif (is_callable($this->rule)) {
                          $savename = call_user_func($this->rule);
                      } else {
                          $savename = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true));
                      }
              }
          }
    
          return $savename;
      }
    复制代码

$this->rule 默认值 date 因此生成 文件名的是this

$savename = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true));
复制代码

md5 加密 当前微秒浮点数加密

在循环的时候在同一时间调用了该方法因此生成了 一样的文件名spa

如何解决

生成文件名的规则能够传入回调, 本身实现一个 生成的回调函数调试

在项目根目录的common.php 文件中 建立一个公共函数

if (!function_exists('autoBuild')) {

    /**
     * /*
     * 自定义生成文件名生成规则
     * thinkphp 框架采用微秒时间戳生成致使批量上传时生成重复名称
     *
     * @param $rule  加密方法
     * @return string
     */
    function autoBuild($rule='sha256'){
        if (!in_array($rule, hash_algos())) {
            $rule='md5';
        }
        $uuid=guid();
        $hash=hash($rule, time().mt_rand(1000,9999).$uuid);

        $savename = date('Ymd') . DIRECTORY_SEPARATOR . substr($hash, 2,36);
        return $savename;
    }

}

/**
 * 生成惟一ID
 */
if (!function_exists('guid')) {
    function guid()
    {
        if (function_exists('com_create_guid')) {
            return com_create_guid();
        } else {
            mt_srand((double)microtime() * 10000);//optional for php 4.2.0 and up.
            $charid = strtoupper(md5(uniqid(rand(), true)));
            $hyphen = chr(45);// "-"
            $uuid = chr(123)// "{"
                . substr($charid, 0, 8) . $hyphen
                . substr($charid, 8, 4) . $hyphen
                . substr($charid, 12, 4) . $hyphen
                . substr($charid, 16, 4) . $hyphen
                . substr($charid, 20, 12)
                . chr(125);// "}"
            return $uuid;
        }
    }
}
复制代码

修改控制器的调用

public function upload(){
    // 获取表单上传文件
    $files = request()->file('image');
    foreach($files as $file){
        // 移动到框架应用根目录/uploads/ 目录下  使用 autoBuild 构建文件名
        $info = $file->rule('autoBuild')->move( '../uploads');
        if($info){
            // 成功上传后 获取上传信息
            // 输出 jpg
            echo $info->getExtension(); 
            // 输出 42a79759f284b767dfcb2a0197904287.jpg
            echo $info->getFilename(); 
        }else{
            // 上传失败获取错误信息
            echo $file->getError();
        }    
    }
}
复制代码

结束

相关文章
相关标签/搜索