Yii Framework 2.0 Uploading Files Error finfo_file

2020-02-10 14:41发布

问题:

Following Yii Framework 2.0 documentation http://www.yiiframework.com/doc-2.0/guide-input-file-upload.html I tried to upload image. The image could be uploaded successfully, but after uploading the image, I tried to insert the model into the database with the following code.

 $model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);

 $model->save();

I got the following error:

 PHP Warning – yii\base\ErrorException

 finfo_file(/tmp/phpIGuwiT): failed to open stream: No such file or directory

 1. in /var/www/html/website/advanced/vendor/yiisoft/yii2/helpers/BaseFileHelper.php
 if ($info) {
        $result = finfo_file($info, $file);
        finfo_close($info);

        if ($result !== false) {
            return $result;
        }
    }

 2. in /var/www/html/my-project/advanced/vendor/yiisoft/yii2/validators/FileValidator.php – yii\helpers\BaseFileHelper::getMimeType()
  $mimeType = FileHelper::getMimeType($file->tempName, null, false);

 3.
 4.
 and so on ....

The result is that image has been uploaded but the model has not been inserted into the database. Does anyone know how to solve this?

回答1:

I was having the exact same problem, and I solved it by calling

$model->save();

before

$model->file->saveAs()

I don't know how your model looks like, but if you are just saving the actual file on the server, and only the path to the image in the DB, it should work.

I think what happens is that when you call file->saveAs() before model->save, the model validation fails because 'file' no longer contains the uploaded data (it is already saved as...). Hope it makes sense.



回答2:

 $model->file->saveAs();

 //try delete imageFile file variable before save model

 $model->imageFile = null;

 $model->save();


回答3:

I was having same same problem, I solve with this.

$model->file->saveAs($filepath , false)

then

$model->save(false)

Important : in saveAs function pass False parameter.



回答4:

This issue can be caused by two issues, not just what is stated in other answers:

  1. PHP file size limits - you need to make sure your PHP settings allow you to upload files that are big enough. By default, PHP only allows 2mb files, so if you try to upload more, you may encounter this error and have no idea why.

You can change it by editing your php.ini file settings:

memory_limit = 32M
upload_max_filesize = 24M
post_max_size = 32M

Make sure post_max_size is bigger than or equal to upload_max_file_size and memory_limit is bigger than or equal to post_max_size.

  1. Model validation fails - the model no longer contains the uploaded temp post data. Therefore, you need to validate the model before saving it (note this won't consistently happen across environments / server set ups so best to be safe).

Here is a practical and real life example of how you would use it in your controller:

$model->upload_file = UploadedFile::getInstance($model, 'upload_file');

if ($model->validate()) {
    if ($model->upload_file->saveAs('my/path/filename.txt')) {
        $model->upload_file = null; 
        $model->save(false);
        return ['status' => 'success']; // return your custom success
     } else return ['status'=>'error']; // return your validation errors
    }
} else return ['status'=>'error']; // return your validation errors


回答5:

You need to call $model->save() first then $model->file->saveAs(). Below is the code for reference.

if($model->file) {   
    $imagename = 'Profile_'.$model->created_at.rand(100000, 999999);
    $model->profilepic = $imagename.'.'.$model->file->extension;
    $path = 'uploads/';
}

if($model->save()) {
    $model->file ? $model->file->saveAs($path.$imagename.'.'.$model->file->extension): null;
    //the render or redirect code goes here on success
} else {
    //if the validation fails then it will be executed
}



回答6:

Do as follows

$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
// rewrite the file attribute to saved url of the file.
$model->file = 'uploads/' . $model->file->baseName . '.' . $model->file->extension;
$model->save();

Hope this helps!



回答7:

My solution looks like this:

    $model = new Film();
    $uploads = Yii::getAlias('@uploads'); // Alias root_dir/uploads

    if ($model->load(Yii::$app->request->post())) {
        $file = UploadedFile::getInstance($model, 'poster');

        $imageName = rand(9999, 999999);

        $file->name = $imageName . '.' . $file->extension; // override the file name

        $model->poster = $file;

        if($model->validate() && $model->save()) {
            $file->saveAs($uploads . '/posters/' . $model->poster);
            return $this->redirect(['view', 'id' => $model->film_id]);
        }

    }

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


回答8:

Replace

$model->save()

by

$model->save(false)

This is because when you perform $model->save() with no argument, it will by default consider true ie the input must be validated (reference). And all inputs must be validated before uploading or saving in database ie above

$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);

line and

$model->save()

line

So finally my suggestion is

In your XyzController.php (in "create" (actionCreate possibly) scenario)

...
...

if($model->validate())  // in "create" (actionCreate possibly) scenario
{
    $model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
    $model->save(false);
}
else
{
    $msg = 'Error in saving data! Invalid data';
    return $this->render('back', ['err_msg'=>$msg]);
}
...
...

This would work fine in create scenario, but what about "update" (actionUpdate possibly) scenario? In that case I have tested Aleksandr Ivin's (above) answer and it's working fine. Here is the description

If image uploading is not mandatory than

...
...
if($model->image_file = UploadedFile::getInstance($model, 'image_file'))
{
    // do all uploading stuffs here like below line
    $model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
}
$model->image_file = null;
if($model->save(true))
{
    $msg = 'Success!';     // set this as flash message if you need
    return $this->redirect(['index']);
}
...
...


回答9:

try $model->file->saveAs($filepath, false) instead of $model->file->saveAs($filepath)
or set $model->file = null before calling $model->file->saveAs() will solve the problem



回答10:

when we save to image field in db, just use

$model->file->name;

when you try to print $model->file you will get an array

print_r($model->file); die();