Php 递归上载文件夹及其内容,但使其结构符合逻辑

Php 递归上载文件夹及其内容,但使其结构符合逻辑,php,file-upload,yii2,directory,directory-upload,Php,File Upload,Yii2,Directory,Directory Upload,目标目标: a) 上载.zip文件,在我的服务器上的临时目录中提取其组件 b) 在一个位置复制/移动所有文件,但对所有文件进行唯一重命名,以便两个文件的名称(在物理位置)不相同 c) 在数据库中开发一个逻辑文件夹树结构(在复制并存储到数据库中时注意文件夹名称,同时存储其内容文件,以便所有文件都具有其所属文件夹的父id) 解释: 压缩文件上载到common/uploads/directories/FolderName.zip,解压缩到common/uploads/directories/Extra

目标目标:

a) 上载.zip文件,在我的服务器上的临时目录中提取其组件

b) 在一个位置复制/移动所有文件,但对所有文件进行唯一重命名,以便两个文件的名称(在物理位置)不相同

c) 在数据库中开发一个逻辑文件夹树结构(在复制并存储到数据库中时注意文件夹名称,同时存储其内容文件,以便所有文件都具有其所属文件夹的父id)

解释:

压缩文件上载到common/uploads/directories/FolderName.zip,解压缩到common/uploads/directories/ExtractedArchive/FolderName,然后根据定义的文件规则验证每个文件,如果验证,则复制到common/uploads/files位置/

这些文件共享相同的物理位置,但在db中,它们以下面的方式连接(递归,无限深度)

  • 文件夹名
    • File1.html
    • File2.txt
    • 测试文件夹
      • 文件3.pdf
      • File4.doc
      • 另一个测试文件夹
        • docx file.docx
        • 文档文件.pdf
      • file5.jpg
同样,所有文件都位于服务器的同一目录中,但它们通过逻辑目录树结构相互连接。 在db中会变成如下所示:

fileId | filename            | type   | parent

1      | FolderName          | folder | null
2      | File1.html          | file   | 1
3      | File2.txt           | file   | 1
4      | TestFolder          | folder | 1
5      | File3.doc           | file   | 4
6      | file4.pdf           | file   | 4
7      | Another Test Folder | folder | 4
8      | docx file.docx      | file   | 7
9      | document file.pdf   | file   | 7
10     | file5.jpg           | file   | 4
等等

以下是我编写的任务的相关代码段: view.php文件

<div class="modmgt-module-create">
  <div class="panel panel-default">
    <div class="panel-heading h4"><?php echo Html::encode($this->title); ?></div>
    <div class="panel-body">    
        <div class="modmgt-module-form">
            <?php $form = ActiveForm::begin(); ?>
            <?php echo $form->field($model, 'uploadedFile')->fileInput(); ?>
            <?php echo $form->field($model, 'description')->textarea(['class'=>'form-control', 'style'=>'max-width:100%; min-height:150px;']); ?>
            <?php echo $form->field($model, 'idcategory')->dropDownList($categories, ['prompt'=>Yii::t('main', 'Please Select')]); ?>
            <div class="form-group">
                <?php echo Html::submitButton(Yii::t('main', 'Upload Folder'), ['class' => 'btn btn-primary']); ?>
            </div>
            <?php ActiveForm::end(); ?>
        </div>
    </div>
  </div>  
</div>
public function actionUploadDirectory($pid = null)
{
    $model = new DirectoryUploadForm();
    $model->parent = $pid;  //  The ID of parent Directory (coming from the get request)

    if($model->load(Yii::$app->request->post()))
    {
        $UploadedZipFile = \yii\web\UploadedFile::getInstance($model, 'uploadedFile');

        if(null != $UploadedZipFile)
        {
            //  Step - 01 - Upload File on my Server (Works fine)
            //  Step - 02 - Extract that .zip file at my server (works fine)
            //$zipExtractDir = Yii::getAlias('@common/uploads/directories/ExtractedArchive/').$UploadedZipFile->baseName;

            //  Step - 03 - Visit the Directory Recursively and add files in db if meet the requirements
            $model->name = $UploadedZipFile->baseName;
            $status = DirectoryUploadForm::addFilesfromDirectory($zipExtractDir, $model); // now this is where I get the problem
            if(!$status)
            {
                Yii::$app->session->addFlash("error", Yii::t("main","Contents could not be added in db and Server"));
            }

            //  Step - 04 - Delete the uploaded .zip file and its extracted directory (works fine)

            return $this->redirect(['index', 'parent'=>$pid]);
        }
        else
        {
            Yii::$app->session->addFlash("error", Yii::t("main","Please upload a file"));
            return $this->redirect(['index', 'parent'=>$pid]);
        }
    }
    else
    {
        return $this->render('upload_directory', ['model' => $model]);
    }
}
const TYPE_FOLDER = 1;
const TYPE_FILE = 2;
public function rules()
{
    return [
        [['name', 'uid', 'idstatus', 'type', 'idcategory', 'author', 'created'], 'required'],
        [['description'], 'string'],
        [['idstatus', 'type', 'parent', 'rating', 'views', 'idcategory', 'author'], 'integer'],
        [['created', 'updated'], 'safe'],
        [['name'], 'string', 'max' => 64],
        [['extension', 'uid'], 'string', 'max' => 45],
        [['idstatus'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtStatus::className(), 'targetAttribute' => ['idstatus' => 'idstatus']],
        [['idcategory'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtCategory::className(), 'targetAttribute' => ['idcategory' => 'idcategory']],
        [['parent'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtFile::className(), 'targetAttribute' => ['parent' => 'idfile']],
    ];
}
public function addFilesFromDirectory($dirname, $currentModel, $depth = 0, $status = true )
{
    // Step - 01 - Add a Directory of name given as $direname
    $temp = explode('/', $dirname);
    $name = end($temp);
    //                 $name = $currentModel->name;
    $parent = $currentModel->parent;
    $description = $currentModel->description;
    $idcategory = $currentModel->idcategory;

    $extension = '0';  //  0 is for No Extension at all
    $uid = md5($name.time());
    $type = FilemgtFile::TYPE_FOLDER;

    $currentModelId = // add this as directory-structure-model and get its PK // works fine
    if(0 == (int)$currentModelId)   //  means we were unable to create a db record for it
    {
        Yii::$app->session->addFlash("error", Yii::t("main", "Directory with name: {$name} could not be added in db"));
        return false;
    }
    else
    {
        Yii::$app->session->addFlash("success", Yii::t("main", "Directory with name: {$name} has been added successfully. . ."));
        $status &= true;
    }
    // Step - 02 - Traverse the newly created directeory ($direname)

    $dir = new \RecursiveDirectoryIterator(Yii::getAlias($dirname.DIRECTORY_SEPARATOR));
    while ($dir->valid())
    {
       if(!$dir->isDot())   //  To skip the items with . and ..
       {

           if($dir->isFile())  //  It is a file
           {
               $file = $dir->current();
               $name = $file->getFilename();
               $parent = $currentModel->parent;
               $description = $currentModel->description;
               $idcategory = $currentModel->idcategory;
               $extension = $file->getExtension();
               $uid = md5($name.'_'.time()).'.'.$extension;
               $type = FilemgtFile::TYPE_FILE;
               $lastInsertId = // add this file-model in database
               if(0 == (int)$lastInsertId) //  case: the db Insertion failed for the file
               {
                   Yii::$app->session->addFlash("error", Yii::t("main", "File with name: {$name} could not be added in db"));
                   return false;
               }
               else
               {
                   // Copy Files from main location to new one
                   $status &= self::copyFilesFromFolder(Yii::getAlias($dirname.DIRECTORY_SEPARATOR.$name), $uid); // works fine


                   // Create Thumbnails for Image files
                   $status &= self::createThumbnails(Yii::getAlias($dirname.DIRECTORY_SEPARATOR.$name), $file);  // works fine

               }
           }
           else if($dir->isDir())   //  It is a directory
           {
               $subDir = Yii::getAlias($dir->current());
               $childModel = new DirectoryUploadForm();
               $childModel->parent = $currentModelId;
               $childModel->description = $currentModel->description;
               $childModel->idcategory = $currentModel->idcategory;

               $status &= self::addFilesFromDirectory($subDir, $childModel, $depth++, $status);
               if(!$status)
               {
                   Yii::$app->session->addFlash("error", Yii::t("main", "Directory (and contents) with name: {$name} could not be added in db"));
               }
           }
       }
       $dir->next();
   }
   return $status;
}

FilemgtFile.php文件

<div class="modmgt-module-create">
  <div class="panel panel-default">
    <div class="panel-heading h4"><?php echo Html::encode($this->title); ?></div>
    <div class="panel-body">    
        <div class="modmgt-module-form">
            <?php $form = ActiveForm::begin(); ?>
            <?php echo $form->field($model, 'uploadedFile')->fileInput(); ?>
            <?php echo $form->field($model, 'description')->textarea(['class'=>'form-control', 'style'=>'max-width:100%; min-height:150px;']); ?>
            <?php echo $form->field($model, 'idcategory')->dropDownList($categories, ['prompt'=>Yii::t('main', 'Please Select')]); ?>
            <div class="form-group">
                <?php echo Html::submitButton(Yii::t('main', 'Upload Folder'), ['class' => 'btn btn-primary']); ?>
            </div>
            <?php ActiveForm::end(); ?>
        </div>
    </div>
  </div>  
</div>
public function actionUploadDirectory($pid = null)
{
    $model = new DirectoryUploadForm();
    $model->parent = $pid;  //  The ID of parent Directory (coming from the get request)

    if($model->load(Yii::$app->request->post()))
    {
        $UploadedZipFile = \yii\web\UploadedFile::getInstance($model, 'uploadedFile');

        if(null != $UploadedZipFile)
        {
            //  Step - 01 - Upload File on my Server (Works fine)
            //  Step - 02 - Extract that .zip file at my server (works fine)
            //$zipExtractDir = Yii::getAlias('@common/uploads/directories/ExtractedArchive/').$UploadedZipFile->baseName;

            //  Step - 03 - Visit the Directory Recursively and add files in db if meet the requirements
            $model->name = $UploadedZipFile->baseName;
            $status = DirectoryUploadForm::addFilesfromDirectory($zipExtractDir, $model); // now this is where I get the problem
            if(!$status)
            {
                Yii::$app->session->addFlash("error", Yii::t("main","Contents could not be added in db and Server"));
            }

            //  Step - 04 - Delete the uploaded .zip file and its extracted directory (works fine)

            return $this->redirect(['index', 'parent'=>$pid]);
        }
        else
        {
            Yii::$app->session->addFlash("error", Yii::t("main","Please upload a file"));
            return $this->redirect(['index', 'parent'=>$pid]);
        }
    }
    else
    {
        return $this->render('upload_directory', ['model' => $model]);
    }
}
const TYPE_FOLDER = 1;
const TYPE_FILE = 2;
public function rules()
{
    return [
        [['name', 'uid', 'idstatus', 'type', 'idcategory', 'author', 'created'], 'required'],
        [['description'], 'string'],
        [['idstatus', 'type', 'parent', 'rating', 'views', 'idcategory', 'author'], 'integer'],
        [['created', 'updated'], 'safe'],
        [['name'], 'string', 'max' => 64],
        [['extension', 'uid'], 'string', 'max' => 45],
        [['idstatus'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtStatus::className(), 'targetAttribute' => ['idstatus' => 'idstatus']],
        [['idcategory'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtCategory::className(), 'targetAttribute' => ['idcategory' => 'idcategory']],
        [['parent'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtFile::className(), 'targetAttribute' => ['parent' => 'idfile']],
    ];
}
public function addFilesFromDirectory($dirname, $currentModel, $depth = 0, $status = true )
{
    // Step - 01 - Add a Directory of name given as $direname
    $temp = explode('/', $dirname);
    $name = end($temp);
    //                 $name = $currentModel->name;
    $parent = $currentModel->parent;
    $description = $currentModel->description;
    $idcategory = $currentModel->idcategory;

    $extension = '0';  //  0 is for No Extension at all
    $uid = md5($name.time());
    $type = FilemgtFile::TYPE_FOLDER;

    $currentModelId = // add this as directory-structure-model and get its PK // works fine
    if(0 == (int)$currentModelId)   //  means we were unable to create a db record for it
    {
        Yii::$app->session->addFlash("error", Yii::t("main", "Directory with name: {$name} could not be added in db"));
        return false;
    }
    else
    {
        Yii::$app->session->addFlash("success", Yii::t("main", "Directory with name: {$name} has been added successfully. . ."));
        $status &= true;
    }
    // Step - 02 - Traverse the newly created directeory ($direname)

    $dir = new \RecursiveDirectoryIterator(Yii::getAlias($dirname.DIRECTORY_SEPARATOR));
    while ($dir->valid())
    {
       if(!$dir->isDot())   //  To skip the items with . and ..
       {

           if($dir->isFile())  //  It is a file
           {
               $file = $dir->current();
               $name = $file->getFilename();
               $parent = $currentModel->parent;
               $description = $currentModel->description;
               $idcategory = $currentModel->idcategory;
               $extension = $file->getExtension();
               $uid = md5($name.'_'.time()).'.'.$extension;
               $type = FilemgtFile::TYPE_FILE;
               $lastInsertId = // add this file-model in database
               if(0 == (int)$lastInsertId) //  case: the db Insertion failed for the file
               {
                   Yii::$app->session->addFlash("error", Yii::t("main", "File with name: {$name} could not be added in db"));
                   return false;
               }
               else
               {
                   // Copy Files from main location to new one
                   $status &= self::copyFilesFromFolder(Yii::getAlias($dirname.DIRECTORY_SEPARATOR.$name), $uid); // works fine


                   // Create Thumbnails for Image files
                   $status &= self::createThumbnails(Yii::getAlias($dirname.DIRECTORY_SEPARATOR.$name), $file);  // works fine

               }
           }
           else if($dir->isDir())   //  It is a directory
           {
               $subDir = Yii::getAlias($dir->current());
               $childModel = new DirectoryUploadForm();
               $childModel->parent = $currentModelId;
               $childModel->description = $currentModel->description;
               $childModel->idcategory = $currentModel->idcategory;

               $status &= self::addFilesFromDirectory($subDir, $childModel, $depth++, $status);
               if(!$status)
               {
                   Yii::$app->session->addFlash("error", Yii::t("main", "Directory (and contents) with name: {$name} could not be added in db"));
               }
           }
       }
       $dir->next();
   }
   return $status;
}

DirectoryUploadForm.php文件

<div class="modmgt-module-create">
  <div class="panel panel-default">
    <div class="panel-heading h4"><?php echo Html::encode($this->title); ?></div>
    <div class="panel-body">    
        <div class="modmgt-module-form">
            <?php $form = ActiveForm::begin(); ?>
            <?php echo $form->field($model, 'uploadedFile')->fileInput(); ?>
            <?php echo $form->field($model, 'description')->textarea(['class'=>'form-control', 'style'=>'max-width:100%; min-height:150px;']); ?>
            <?php echo $form->field($model, 'idcategory')->dropDownList($categories, ['prompt'=>Yii::t('main', 'Please Select')]); ?>
            <div class="form-group">
                <?php echo Html::submitButton(Yii::t('main', 'Upload Folder'), ['class' => 'btn btn-primary']); ?>
            </div>
            <?php ActiveForm::end(); ?>
        </div>
    </div>
  </div>  
</div>
public function actionUploadDirectory($pid = null)
{
    $model = new DirectoryUploadForm();
    $model->parent = $pid;  //  The ID of parent Directory (coming from the get request)

    if($model->load(Yii::$app->request->post()))
    {
        $UploadedZipFile = \yii\web\UploadedFile::getInstance($model, 'uploadedFile');

        if(null != $UploadedZipFile)
        {
            //  Step - 01 - Upload File on my Server (Works fine)
            //  Step - 02 - Extract that .zip file at my server (works fine)
            //$zipExtractDir = Yii::getAlias('@common/uploads/directories/ExtractedArchive/').$UploadedZipFile->baseName;

            //  Step - 03 - Visit the Directory Recursively and add files in db if meet the requirements
            $model->name = $UploadedZipFile->baseName;
            $status = DirectoryUploadForm::addFilesfromDirectory($zipExtractDir, $model); // now this is where I get the problem
            if(!$status)
            {
                Yii::$app->session->addFlash("error", Yii::t("main","Contents could not be added in db and Server"));
            }

            //  Step - 04 - Delete the uploaded .zip file and its extracted directory (works fine)

            return $this->redirect(['index', 'parent'=>$pid]);
        }
        else
        {
            Yii::$app->session->addFlash("error", Yii::t("main","Please upload a file"));
            return $this->redirect(['index', 'parent'=>$pid]);
        }
    }
    else
    {
        return $this->render('upload_directory', ['model' => $model]);
    }
}
const TYPE_FOLDER = 1;
const TYPE_FILE = 2;
public function rules()
{
    return [
        [['name', 'uid', 'idstatus', 'type', 'idcategory', 'author', 'created'], 'required'],
        [['description'], 'string'],
        [['idstatus', 'type', 'parent', 'rating', 'views', 'idcategory', 'author'], 'integer'],
        [['created', 'updated'], 'safe'],
        [['name'], 'string', 'max' => 64],
        [['extension', 'uid'], 'string', 'max' => 45],
        [['idstatus'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtStatus::className(), 'targetAttribute' => ['idstatus' => 'idstatus']],
        [['idcategory'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtCategory::className(), 'targetAttribute' => ['idcategory' => 'idcategory']],
        [['parent'], 'exist', 'skipOnError' => true, 'targetClass' => FilemgtFile::className(), 'targetAttribute' => ['parent' => 'idfile']],
    ];
}
public function addFilesFromDirectory($dirname, $currentModel, $depth = 0, $status = true )
{
    // Step - 01 - Add a Directory of name given as $direname
    $temp = explode('/', $dirname);
    $name = end($temp);
    //                 $name = $currentModel->name;
    $parent = $currentModel->parent;
    $description = $currentModel->description;
    $idcategory = $currentModel->idcategory;

    $extension = '0';  //  0 is for No Extension at all
    $uid = md5($name.time());
    $type = FilemgtFile::TYPE_FOLDER;

    $currentModelId = // add this as directory-structure-model and get its PK // works fine
    if(0 == (int)$currentModelId)   //  means we were unable to create a db record for it
    {
        Yii::$app->session->addFlash("error", Yii::t("main", "Directory with name: {$name} could not be added in db"));
        return false;
    }
    else
    {
        Yii::$app->session->addFlash("success", Yii::t("main", "Directory with name: {$name} has been added successfully. . ."));
        $status &= true;
    }
    // Step - 02 - Traverse the newly created directeory ($direname)

    $dir = new \RecursiveDirectoryIterator(Yii::getAlias($dirname.DIRECTORY_SEPARATOR));
    while ($dir->valid())
    {
       if(!$dir->isDot())   //  To skip the items with . and ..
       {

           if($dir->isFile())  //  It is a file
           {
               $file = $dir->current();
               $name = $file->getFilename();
               $parent = $currentModel->parent;
               $description = $currentModel->description;
               $idcategory = $currentModel->idcategory;
               $extension = $file->getExtension();
               $uid = md5($name.'_'.time()).'.'.$extension;
               $type = FilemgtFile::TYPE_FILE;
               $lastInsertId = // add this file-model in database
               if(0 == (int)$lastInsertId) //  case: the db Insertion failed for the file
               {
                   Yii::$app->session->addFlash("error", Yii::t("main", "File with name: {$name} could not be added in db"));
                   return false;
               }
               else
               {
                   // Copy Files from main location to new one
                   $status &= self::copyFilesFromFolder(Yii::getAlias($dirname.DIRECTORY_SEPARATOR.$name), $uid); // works fine


                   // Create Thumbnails for Image files
                   $status &= self::createThumbnails(Yii::getAlias($dirname.DIRECTORY_SEPARATOR.$name), $file);  // works fine

               }
           }
           else if($dir->isDir())   //  It is a directory
           {
               $subDir = Yii::getAlias($dir->current());
               $childModel = new DirectoryUploadForm();
               $childModel->parent = $currentModelId;
               $childModel->description = $currentModel->description;
               $childModel->idcategory = $currentModel->idcategory;

               $status &= self::addFilesFromDirectory($subDir, $childModel, $depth++, $status);
               if(!$status)
               {
                   Yii::$app->session->addFlash("error", Yii::t("main", "Directory (and contents) with name: {$name} could not be added in db"));
               }
           }
       }
       $dir->next();
   }
   return $status;
}

问题 上载结构未得到维护。我得到的结构是这样出现的:父目录得到的文件实际上属于它的子目录模型。然而,创建子目录模型时也没有包含任何内容。一切都搞砸了

我已经删除了这里没有用的代码,这样你就不必阅读不必要的代码来解决问题;但是如果你需要查看我机器上的完整代码,请告诉我

感谢您的帮助。提前谢谢各位。 保持幸福