Yii 2 File Download

Sometimes we need generated URLs to file downloads to avoid people bookmarking a permanent link to a file.

Create Table

Example fields for table file:

CREATE TABLE `file` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `file_path` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  `hash` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  `active` TINYINT(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

Create Active Record model for this table using Gii.

Controller

Create action actionDownload() in controller. When downloading, require a $hash as parameter:

class FileController extends Controller
{
  //...
 
  public function actionDownload($hash)
  {
    $model = FileModel::find()->where(['hash'=>$hash])->one();
 
    if ($model && $model->active == 1) {
        $file = $model->file_path;
        $model->active = 0;
        $model->save(false);
        return $this->render('download', ['file' => $file]);
    }
 
    return $this->render('downloadLinkExpired');
  }
}  
View
if (file_exists($file)) {
    Yii::$app->response->sendFile($file);
}

Then, in form controller

  • Generate an MD5 hash based on current time and maybe some form fields (just to avoid duplicated hash).
  • For every link, save new model in database.
  • Render links with hash parameter.
    Url::toRoute('file/download', ['hash'=>$hash])

Source: StackOverflow: Yii2 - How to dynamically generate download file link