Yii2 POST image to model in API without Yii2 Namin

2019-07-29 14:17发布

I'm creating an endpoint for a mobile application to send a image to the server. I'm posting the image with the POSTMAN extension for chrome. The image is in the $_FILES variable, and named image. How can I load this image into a model, or the UploadedFile class? The $model->load(Yii::$app->request->post()) line does not correctly load the file, as it is not in Yii2's naming convention for forms.

It's currently returning:

{
    "success": false,
    "message": "Required parameter 'image' is not set."
}

Code

models\Image.php

<?php
namespace api\modules\v1\models;

use yii\base\Model;
use yii\web\UploadedFile;

class Image extends Model
{
    /**
     * @var UploadedFile
     */
    public $image;

    public function rules()
    {
        return [
            [['image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
        ];
    }

    public function upload()
    {
        $path = dirname(dirname(__FILE__)) . '/temp/';
        if ($this->validate()) {
            $this->image->saveAs($path . $this->image->baseName . '.' . $this->image->extension);
            return true;
        } else {
            die(var_dump($this->errors));
            return false;
        }
    }
}

controllers\DefaultController.php

<?php
namespace api\modules\v1\controllers;

use api\modules\v1\models\Image;
use yii\web\Controller;
use yii\web\UploadedFile;
use Yii;

class DefaultController extends Controller
{
    public $enableCsrfValidation = false;

    public function actionIndex()
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $model = new Image();

        if (Yii::$app->request->isPost) {
            if($model->load(Yii::$app->request->post()))
            {
                $model->image = UploadedFile::getInstance($model, 'image');
                if ($model->upload()) {
                    // file is uploaded successfully
                    return ['success' => true, 'message' => 'File saved.'];
                }
                else return ['success' => false, 'message' => 'Could not save file.'];
            }
            else return ['success' => false, 'message' => 'Required parameter \'image\' is not set.'];
        }
        else return ['success' => false, 'message' => 'Not a POST request.'];
    }
}

Postman Postman POST request

标签: yii2
2条回答
Bombasti
2楼-- · 2019-07-29 15:00

Your problem seems to be the name you are using to send the image file. Usually Yii2 uses names for form attributes like "ModelName[attributeName]" and you are sending your image file with the name "image"

There are 2 ways of fixing this:

  1. Change the name you use to send your image file to follow the same naming conveniton. However you don't seem to want that.
  2. Use getInstanceByName('image') method instead of getInstance($model, 'image')
查看更多
女痞
3楼-- · 2019-07-29 15:07

The problem come here When you send files via api they are not sent asynchronously. If you check

echo '<pre>';
 print_r($_FILES); //returns nothing 
 print_r($_POST["image"]);  //returns something
 echo '</pre>';
die;

One reason is that your controller extendsyii\web\controller which is not used by rest apis, extend yii\rest\controller

The other way to go about this is by using javascript formData when sending the post request

This is a way i handled a previous ajax post of an image probably itll give you a guideline

The form
 <?php $form = ActiveForm::begin(['options' => ['enctype' => 
  'multipart/form-data','id'=>'slider_form']]); ?>  //dont forget enctype

 <?= $form->field($model, 'file')->fileInput() ?>

Then on the ajax post

 var formData = new FormData($('form#slider_form')[0].files);

$.post(
    href, //serialize Yii2 form 
    {other atributes ,formData:formData}
)

Then on the controller simply access via
$model->file =$_FILES["TblSlider"]; //here this depends on your form attributes check with var_dump($_FILES)
$file_tmp = $_FILES["TblSlider"]["tmp_name"]["file"];
        $file_ext = pathinfo($_FILES['TblSlider']['name']["file"], PATHINFO_EXTENSION);

        if(!empty($model->file)){

            $filename = strtotime(date("Y-m-d h:m:s")).".".$file_ext;

            move_uploaded_file($file_tmp, "../uploads/siteimages/slider/".$filename);
            ///move_uploaded_file($file_tmp, Yii::getAlias("@uploads/siteimages/slider/").$filename);
            $model->image = $filename;
        }

I hope this helps

查看更多
登录 后发表回答