4

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.

2 Answers 2

9

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],
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the advice about checkExtensionsByMimeType. I was struggling with that.
0

What is your FORM markup? View the page source within the browser. Files are ignored unless the form markup has has multipart/form-data.

<form action="upload.php" method="post" enctype="multipart/form-data">

2 Comments

I added it. Also if you read the bottom paragraph if I have 'skipOnEmpty'=>true everything uploads and saves fine.
Yii2 adds the enctype attribute automatically when the form has a file input.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.