2

Target Objective:

a) Upload a .zip file, extract its components in a temp directory on my server

b) copy/move all files in one place but rename all files uniquely so that no two files have same name (at physical location)

c) develop a logical folder tree structure in db (note the folder name while copying and store that in db, also store its content files such that all files have parent id of that folder they belong to)

Explaination:

The compressed file is uploaded at common/uploads/directories/FolderName.zip, is extracted to common/uploads/directories/ExtractedArchive/FolderName and then each file is validated according to file rules defined and then if validated, are copied to a location common/uploads/files/

These files are at share same physical location but in db they are connected in below way (recursive, unlimited depth)

  • FolderName
    • File1.html
    • File2.txt
    • TestFolder
      • File3.pdf
      • File4.doc
      • Another Test Folder
        • docx file.docx
        • document file.pdf
      • file5.jpg
    • .
    • . .
    • . . .

Once again, all the files are in same directory at server but they are connected to each other via logical directory tree structure. This becomes something like below in 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

and So on....

Below are the related code segnents for the task I have written:

view.php file

<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 file

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 file

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 file

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

Problem The upload structure is not getting maintained. I am getting structure appeared in such a way that a parent directory is getting files in it that actually belong to its child-directory-model. Yet the child directory-model is also getting created with no content it it. Its all messed up.

I have eliminated the code that is not of use here so that you don't have to read unnecessary code to get to the problem bottom-line; but let me know if you need to see the full code I have on my machine.

Any help is appreciated. Thanks in advance guys. Stay blessed.

ahmednawazbutt
  • 823
  • 12
  • 34

0 Answers0