php:实现压缩文件上传、解压、文件更名、压缩包删除功能

效果图

1.上传文件

2.压缩包文件

3.itemno1文件

4.上传到系统路径\ItemNo

5.更名后的itemno1文件(命名:当天日期+六位随机数)

代码

<form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8'); ?>" method="post" enctype="multipart/form-data">
  <input type="hidden" name="FormID" value="<?php echo $_SESSION['FormID']; ?>">
  <input type="file" name="folderArchive[]" accept=".zip" multiple>
  <input type="submit" value="上传" name="update">
</form>

<?php
//指定路径
$target_dir = "ItemNo/";
// 临时解压目录(新建后会被删除)
$unpack_dir = 'ItemNo_Updates/';
//开始上传
if (isset($_POST['update'])) {
  // 判断是否有上传的文件
  if (isset($_FILES['folderArchive']) && !empty($_FILES['folderArchive']['name'])) {
    //设定一个变量,值为上传的文件信息
    $zip_files = $_FILES['folderArchive'];
    //对上传的文件的name值(例如test.zip)进行遍历
    foreach ($zip_files['name'] as $key => $file_name) {
      //检验文件是否是zip文件
      // pathinfo() 函数用于解析路径信息:PATHINFO_EXTENSION参数,表明它会返回文件路径中的扩展名部分(如zip、txt 等)
      // 将 pathinfo() 返回的扩展名转换为小写形式,
      if (strtolower(pathinfo($file_name, PATHINFO_EXTENSION)) !== 'zip') {
        // sprintf 函数:格式化字符串输出的函数
        prnMsg(sprintf(_('文件 "%s" 不是ZIP格式,请上传ZIP文件.'), $file_name), 'error');
        // 如果不是zip文件就,跳过此文件(将不再做上传等操作),继续执行后面的上传文件
        continue;
      }
      //判断每一条数据的error值:看是否上传成功(UPLOAD_ERR_OK表示长传成功)
      if ($zip_files['error'][$key] === UPLOAD_ERR_OK) {
        //取出该条数据的tmp_name值(获取上传文件的临时存储路径)
        $temp_file = $zip_files['tmp_name'][$key];
        // 先创建并打开 ZipArchive 对象,创建一个新的ZipArchive对象(ZipArchive用于读取、创建、更新和提取ZIP格式的压缩文件)
        $zip = new ZipArchive;
        //打开压缩文件
        if ($zip->open($temp_file) === TRUE) {
          //创建临时解压目录
          mkdir($unpack_dir, 0755, true);

          // 验证ZIP文件结构
          //设置一个变量用于判断结构是否合规
          $structure_valid = true;
          //遍历ZipArchive对象(通过 $zip 引用)中的所有文件.numFiles是压缩包内的文件数量
          for ($i = 0; $i < $zip->numFiles && $structure_valid; $i++) {
            // 获取指定索引 $i 处的ZIP压缩包内文件的名称
            $filename = $zip->getNameIndex($i);
            //将返回一个数组,数组中的每个元素对应于字符串中两个斜杠(/)之间的部分
            $path_parts = explode('/', $filename);
            // 检查文件路径分隔符个数,必须是两层结构
            if (count($path_parts) != 2) {
              //如果不是两层结构,结构不正确
              $structure_valid = false;
              prnMsg(sprintf(_('文件 "%s" 的内部结构不符合要求(必须是 ZIP -> (一级目录) -> 文件 的结构,至少要有一级子目录).'), $file_name), 'error');
              //跳出循环
              break;
            }
          }
          //如果结构正确
          if ($structure_valid) {
            // 解压缩文件
            $zip->extractTo($unpack_dir);
            // 关闭已经打开的 ZipArchive 对象的(与open对应)
            $zip->close();
            // 获取解压后每个料号(子文件夹)的路径,取$target_dir目录下的所有子目录名称,并将这些名称作为一个数组赋值给$subDirs。
            // $target_dir . '*':表示匹配$target_dir目录下的任何子字符串(在这里实际上指的是子目录名)
            // GLOB_ONLYDIR 是 glob() 函数的一个标志参数,当设置这个标志时,glob() 函数只会返回与指定模式匹配的目录名
            $subDirs = glob($unpack_dir . '*', GLOB_ONLYDIR);
            //遍历每个文件夹的文件
            foreach ($subDirs as $subDir) {
              // 获取料号名称(文件夹名称)
              $itemNo = basename($subDir);
              // 获取子文件夹中的所有文件
              $temp_sub_dir_files = glob($subDir . '/*');
              //循环子文件中的文件
              foreach ($temp_sub_dir_files as $file) {
                // 如果 $file 是一个目录,跳过
                if (is_dir($file)) {
                  continue;
                }
                //验证文件是否已在目标目录中存在
                //获取文件名称
                $fileName = basename($file);
                // 获取目标目录下所有文件和目录的名字
                $existingFiles = scandir($target_dir);
                // 如果文件不在目标目录现存文件列表中,则是新上传的文件
                if (!in_array($fileName, $existingFiles)) {
                  //获取当前日期
                  $dateForFilename = date('Ymd');
                  //生成随机数
                  $random_number = generateUniqueRandomNumber($target_dir, $dateForFilename);
                  // 构建新的文件名YMD_六位随机数(pathinfo用于从文件路径 $file 中提取出文件扩展名。)
                  $newFileName = $dateForFilename . '_' . sprintf('%06d', $random_number) . '.' . pathinfo($file, PATHINFO_EXTENSION);
                  //新文件路径
                  $new_path = $subDir . '/' . $newFileName;
                  // 重命名文件
                  rename($file, $new_path);

                  // $target_dir 是一个变量,它包含了目标目录的完整路径。
                  // $itemNo 是另一个变量,它代表了要创建的子目录的名称或者是某种项目的唯一标识符。
                  $targetSubDir = $target_dir . $itemNo;
                  // 检查 $targetSubDir 是否已经存在且是一个目录
                  if (!is_dir($targetSubDir)) {
                    // 调用 mkdir() 函数尝试创建这个子目录
                    // 第一个参数是待创建目录的路径名,即 $targetSubDir。
                    // 第二个参数 0755 是指创建的目录的权限模式。这是一个八进制数,转换成二进制后表示所有者有读写执行权限,同组用户和其他用户有读和执行权限,但没有写入权限。
                    // 第三个参数 true 表示如果父级目录不存在,也将递归创建它们(即允许创建多级目录)。
                    mkdir($targetSubDir, 0755, true);
                  }

                  // 将处理完的文件移动到最终目标目录
                  rename($new_path, $targetSubDir . '/' . $newFileName);

                  // 插入数据库
                  $time = time();
                  //获取文件名称(去掉后缀)
                  $baseNameWithoutExt = pathinfo($new_path, PATHINFO_FILENAME);
                  $sql = "INSERT INTO bom_headers_all_file
                  (
                    bom_header_id,
                    file_name,
                    file_desc,
                    file_patch,
                    creation_date,
                    created_by,
                    last_update_by,
                    last_update_date,
                    enable_flag
                  )
                  VALUES (
                    '1',
                    '" . $baseNameWithoutExt . "',
                    '" . $itemNo . "',
                    '" . $targetSubDir . '/' . $newFileName . "',
                    '" . $time . "',
                    '" . $_SESSION['UserID'] . "',
                    '" . $time . "',
                    '" . $_SESSION['UserID'] . "',
                    'Y'
                  )";

                  $result = DB_query($sql, $db);
                  // prnMsg(sprintf(_('文件 "%s" 在料号 "%s" 下已成功上传并重命名为 "%s" 并已插入数据库.'), basename($file), $itemNo, $newFileName), 'success');
                }
              }
            }
            // 删除临时解压目录及其内容
            delTree($unpack_dir);
            prnMsg(sprintf(_('文件 "%s" 上传成功.'), $file_name), 'success');
          } else {
            // 结构不合法,关闭ZIP资源并删除临时解压目录
            $zip->close();
            delTree($unpack_dir);
            continue; // 跳过该文件,进入下一个文件的处理
          }
        } else {
          prnMsg(sprintf(_('文件 "%s" 上传成功但无法解压.'), $file_name), 'error');
        }
      } else {
        prnMsg(sprintf(_('文件 "%s" 上传失败.'), $file_name), 'error');
      }
    }
    unset($_POST['update']);
  } else {
    prnMsg(_('附件上传失败!'), 'error');
  }
}

// 定义一个函数,生成当天内不重复的六位随机数
function generateUniqueRandomNumber($dir, $dateForFilename)
{
  //用do-while循环去判断文件名是否存在,如果存在就在此循环直到不存在为止
  do {
    // 生成一个介于100000到999999之间的随机整数
    $random_number = mt_rand(100000, 999999);
    //拼接字符串(/path/YMD_123456.ext 的字符串)(.ext 是一个占位符,表示文件的扩展名,实际应用中应替换为具体的文件类型如 .jpg, .txt, .pdf 等。)
    $filePath = $dir . '/' . $dateForFilename . '_' . sprintf('%06d', $random_number) . '.ext';
  } while (file_exists($filePath)); //检查指定的文件路径 $filePath 是否存在。
  //跳出循环后返回随机数
  return $random_number;
}

// 定义一个递归删除目录及其内容的函数
function delTree($dir)
{
  // array_diff(scandir($dir), array('.', '..')) 从上述数组中排除.
  // (当前目录)和 ..(上级目录),得到的就是该目录下所有实际的文件和子目录名称,然后将其赋值给 $files。
  $files = array_diff(scandir($dir), array('.', '..'));
  // 使用 foreach 循环遍历 $files 数组中的每一个文件或子目录
  foreach ($files as $file) {
    // (is_dir("$dir/$file")) 判断当前 $file 是否为子目录。
    // 如果 $file 是子目录,则调用 delTree("$dir/$file") 函数递归删除这个子目录及其内部的所有文件和子目录。
    // 如果 $file 不是子目录(即普通文件),则调用 unlink("$dir/$file") 函数删除这个文件。
    (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
  }
  //  删除最初传入的 $dir 目录本身。注意,只有当该目录为空时,rmdir() 才能成功删除目录。
  return rmdir($dir);
}
?>

相关推荐

  1. Python压缩文件

    2024-04-15 01:08:01       37 阅读
  2. Go 文件压缩

    2024-04-15 01:08:01       9 阅读
  3. Ubuntu 大压缩文件工具

    2024-04-15 01:08:01       16 阅读
  4. android文件压缩

    2024-04-15 01:08:01       17 阅读
  5. 在Linux中,删除压缩文件的命令

    2024-04-15 01:08:01       54 阅读
  6. unity中压缩文件文件

    2024-04-15 01:08:01       14 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-15 01:08:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-15 01:08:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-15 01:08:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-15 01:08:01       20 阅读

热门阅读

  1. 深度分析thinkphp类的自动加载

    2024-04-15 01:08:01       16 阅读
  2. 启动大模型训练常见的docker参数

    2024-04-15 01:08:01       15 阅读
  3. 支持向量机——SVM

    2024-04-15 01:08:01       17 阅读
  4. python web学习路线

    2024-04-15 01:08:01       15 阅读
  5. 记录一个没测出来,有点严重的Bug

    2024-04-15 01:08:01       14 阅读
  6. pytorch中通道数不一样怎么办?

    2024-04-15 01:08:01       19 阅读
  7. SpringBoot项目中如何使用校验工具

    2024-04-15 01:08:01       15 阅读
  8. 代码随想录-二叉树

    2024-04-15 01:08:01       13 阅读