Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii2 File Validation Not Working After Upload

I'm not sure if this is a new bug or what's going on, but I'm having trouble getting the Yii2 validator to recognize a file is there after it's been uploaded. The client side validation works fine.

Rules for the model:

return [
        [['store_id', 'name', 'csv'], 'required'],
        [['store_id', 'created_at', 'updated_at'], 'integer'],
        [['name'], 'string', 'max' => 255],
        [['csv'], 'file', 'skipOnEmpty' => false, 'maxSize'=>1024 * 1024 * 2],
    ];

Controller Action:

public function actionUploadFromCsv()
{
    $store = Yii::$app->user->identity->store;

    $store_csv = new StoreCsv;
    $store_csv->store_id = $store->id;
    $store_csv->name = $store_csv->getDefaultName();

    if (Yii::$app->request->isPost) {
        $store_csv->csv = UploadedFile::getInstance($store_csv, 'csv');
        if ($store_csv->upload()) {
            return $this->redirect(['view-csv', 'id'=>$store_csv->id]);
        }
        return json_encode($store_csv->getErrors());
    }
    return $this->render('csv_upload', [
        'store'=>$store,
        'csv'=>$store_csv
    ]);
}

Model Upload() Function:

public function upload()
{
    if ($this->validate()) {
        $file_name = uniqid(rand(), false) . '.' . $this->csv->extension;
        $this->csv->saveAs(Yii::getAlias('@backend') . '/web/store/' . $this->store_id . '/csv/' . $file_name);
        $this->csv = $file_name;
        return $this->save();
    }
    return false;
}

Form Markup:

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
    <?= $form->field($csv, 'csv')->fileInput() ?>

    <div class="form-group">
        <?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
    </div>

<?php ActiveForm::end(); ?>

Currently when I perform the upload I get this error after validation fails:

{"csv":["Please upload a file."]}

If I change 'skipOnEmpty' to true, however, it works fine. It saves the model and moves and renames the temporary file. I would like to get validation working though, so I can restrict to certain extensions. What's the deal? I've spent hours trouble shooting this.

like image 566
Jon Robinson Avatar asked Jan 08 '23 08:01

Jon Robinson


1 Answers

I figured out what my problem here is. After saving the file I try to rename it, however, the way I do it here takes away the association of this attribute as a file.

Wrong:

$this->csv = $file_name;

Right:

$this->csv->name = $file_name;

In addition, I originally asked this question because I was having trouble getting the validator to work, restricting extensions. It would not recognize "xls" or "csv" after the client side validation when I did $model->validate(). I just found that this is a known issue due to the MIME TYPE validator: https://github.com/yiisoft/yii2/issues/6148

The solution to the extension issue is to set checkExtensionByMimeType to false:

[['csv'], 'file', 'skipOnEmpty' => false, 'extensions'=>['xls', 'csv'], 'checkExtensionByMimeType'=>false, 'maxSize'=>1024 * 1024 * 2],
like image 193
Jon Robinson Avatar answered Jan 23 '23 00:01

Jon Robinson