2016-08-21 1 views
0

Ich habe eine _form-Ansicht für Update und erstellen. Es gibt ein Dateieingabefeld, in dem nur Zip-Dateien erlaubt sind. Wenn zip hochgeladen wird, sollte es je nach Modellnamen in einen Ordner entpackt werden.Yii2. Warum muss ich die Datei zweimal hochladen, um einen Effekt zu erzielen?

Das Problem ist, ich muss es zwei Mal hochladen, um einen Effekt zu haben, denn das erste Mal gibt mir nicht entpackten Ordner.

Dies ist die Upload-Funktion in Modell

public function upload() 
{ 
    $this->uploadedFile = UploadedFile::getInstance($this, 'filepath'); 

    if (!empty($this->uploadedFile)) { 
     $slug = str_replace(' ', '-', strtolower(trim($this->name))); 
     $htmlPathRel = '/html/' . $slug . '/'; 
     $htmlPathAbs = Yii::getAlias('@frontend') . '/web' . $htmlPathRel; 

     // delete old files before extracting 
     @array_map('unlink', glob($htmlPathAbs . '/*.*')); 
     @rmdir($htmlPathAbs); 

     // unpack new files 
     $zip = new \ZipArchive; 
     if ($zip->open(Yii::getAlias('@frontend') . '/web/uploads/' . $this->uploadedFile->name) === true) { 
      $indexHtmlContent = $zip->getFromName('index.html'); 
      $order = new Order(); 
      $toSearch = array_filter($order->attributes(), function($value) { 
       return strpos($value, 'name="billing_') !== false; 
      }) + array('<form'); 

      if (!$indexHtmlContent) { 
       $this->addError('filepath', 'index.html not found in ' . $this->uploadedFile->name); 
       return false; 
      } 

      $notFound = []; 

      foreach ($toSearch as $string) { 
       if (strpos($indexHtmlContent, $string) === false) { 
        $notFound[] = $string; 
       } 
      } 

      if (!empty($notFound)) { 
       $this->addError('filepath', 'index.html doesn\'t contain required data: ' . implode(', ', $notFound)); 
       return false; 
      } 
      if (!is_dir($htmlPathAbs)) { 
       mkdir($htmlPathAbs); 
      } 
      $zip->extractTo($htmlPathAbs); 
      $zip->close(); 
     } 

     $this->filepath = $htmlPathRel . 'index.html'; 

     $this->save(); 

     if ($this->validate()) { 
      $this->uploadedFile->saveAs(Yii::getAlias('@frontend') . '/web/uploads/' . $this->uploadedFile->baseName . '.' . $this->uploadedFile->extension); 
      return true; 
     } else { 
      return false; 
     } 
    } else { 
     return false; 
    } 
} 

Und das Controller zu erstellen und aktualisieren Aktionen:

/** 
* Creates a new Html model. 
* If creation is successful, the browser will be redirected to the 'view' page. 
* @return mixed 
*/ 
public function actionCreate() 
{ 
    $model = new Html(); 

    if (Yii::$app->request->isPost) { 
     if ($model->load(Yii::$app->request->post())) { 
      Product::updateRoutes(); 
      $model->upload(); 
      $model->save(); 
      return $this->redirect(['view', 'id' => $model->id]); 
     } 
    } 

    return $this->render('create', [ 
     'model' => $model, 
    ]); 
} 

/** 
* Updates an existing Html model. 
* If update is successful, the browser will be redirected to the 'view' page. 
* @param string $id 
* @return mixed 
*/ 
public function actionUpdate($id) 
{ 
    $model = $this->findModel($id); 

    if (Yii::$app->request->isPost) { 
     $filepath = $model->filepath; 
     if ($model->load(Yii::$app->request->post())) { 
      Product::updateRoutes(); 
      if (!$model->upload()) { 
       $model->filepath = $filepath; 
      } 
      $model->save(); 
      return $this->redirect(['view', 'id' => $model->id]); 
     } 
    } 

    return $this->render('update', [ 
     'model' => $model, 
    ]); 
} 

Was mit meinem Code falsch?

PS: alle Code Refactoring Ideen sind willkommen! :)

Antwort

1

Sie speichern die Datei auf @frontend/web/uploads nach dem Entpacken der Datei aus diesem Ordner, so dass es funktioniert nur, wenn die Datei dort ist - zweites Mal.

Verwandte Themen