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

时间:2017-02-22 08:17:27

标签: php file-upload yii2 directory directory-upload

目标目标:

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

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

c)在db中开发逻辑文件夹树结构(注意复制时的文件夹名称并将其存储在db中,同时存储其内容文件,使得所有文件都具有其所属文件夹的父ID)

阐释:

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

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

  • 文件夹名称
    • 的file1.html
    • FILE2.TXT
    • TestFolder
      • File3.pdf
      • File4.doc
      • 另一个测试文件夹
        • docx file.docx
        • document file.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>

controller.php文件

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]);
    }
}

FilemgtFile.php文件

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']],
    ];
}

DirectoryUploadForm.php文件

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;
}

问题 上传结构未得到维护。我得到的结构以这样的方式出现,即父目录中的文件实际上属于其子目录模型。然而,子目录模型也是在没有内容的情况下创建的。一切都搞砸了。

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

感谢任何帮助。先谢谢你们。 保持幸福。

0 个答案:

没有答案