文件上傳(Uploading Files)

2018-02-24 15:40 更新

文件上傳

在Yii里上傳文件通常使用yii\web\UploadedFile類, 它把每個(gè)上傳的文件封裝成?UploadedFile?對(duì)象。 結(jié)合yii\widgets\ActiveForm和models,你可以輕松實(shí)現(xiàn)安全的上傳文件機(jī)制。

創(chuàng)建模型

和普通的文本輸入框類似,當(dāng)要上傳一個(gè)文件時(shí),你需要?jiǎng)?chuàng)建一個(gè)模型類并且用其中的某個(gè)屬性來接收上傳的文件實(shí)例。 你還需要聲明一條驗(yàn)證規(guī)則以驗(yàn)證上傳的文件。 舉例來講,

namespace app\models;

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

class UploadForm extends Model
{
    /**
     * @var UploadedFile
     */
    public $imageFile;

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

    public function upload()
    {
        if ($this->validate()) {
            $this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
            return true;
        } else {
            return false;
        }
    }
}

在以上代碼里,imageFile?屬性用于接收上傳的文件實(shí)例。它對(duì)應(yīng)一條file?驗(yàn)證規(guī)則, 該規(guī)則使用 yii\validators\FileValidator 來確保只上傳擴(kuò)展名為?png?或?jpg?的文件。?upload()?方法會(huì)執(zhí)行該驗(yàn)證并且把上傳的文件保存在服務(wù)器上。

通過?file?驗(yàn)證器,你可以檢查文件的擴(kuò)展名,大小,MIME類型等等。詳情請(qǐng)查閱?Core Validatators?章節(jié)。

提示: 如果你要上傳的是一張圖片,可以考慮使用image驗(yàn)證器。?image?驗(yàn)證器是通過yii\validators\ImageValidator實(shí)現(xiàn)驗(yàn)證的,確保對(duì)應(yīng)的模型屬性 收到的文件是有效的圖片文件,然后才保存,或者使用擴(kuò)展類Imagine Extension進(jìn)行處理.

渲染文件輸入

接下來,在視圖里創(chuàng)建一個(gè)文件輸入控件

<?php
use yii\widgets\ActiveForm;
?>

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

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

    <button>Submit</button>

<?php ActiveForm::end() ?>

需要注意的是要記得在表單選項(xiàng)里加入?enctype?屬性以確保文件能被正常上傳。?fileInput()?方法會(huì)渲染一個(gè)?<input type="file">?標(biāo)簽,讓用戶可以選擇一個(gè)文件上傳。

視圖和模型的連接

現(xiàn)在,在控制器方法里編寫連接模型和視圖的代碼以實(shí)現(xiàn)文件上傳。

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;

class SiteController extends Controller
{
    public function actionUpload()
    {
        $model = new UploadForm();

        if (Yii::$app->request->isPost) {
            $model->imageFile = UploadedFile::getInstance($model, 'imageFile');
            if ($model->upload()) {
                // 文件上傳成功
                return;
            }
        }

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

在上面的代碼里,當(dāng)提交表單的時(shí)候,yii\web\UploadedFile::getInstance()方法就被調(diào)用, 上傳的文件用一個(gè)?UploadedFile?實(shí)例表示。然后,我們依靠模型的驗(yàn)證規(guī)則確保上傳的文件是有效的, 并將文件保存在服務(wù)器上。

上傳多個(gè)文件

將前面所述的代碼做一些調(diào)整,也可以一次性上傳多個(gè)文件。

首先你得調(diào)整模型類,在?file?驗(yàn)證規(guī)則里增加一個(gè)?maxFiles?選項(xiàng),用以限制一次上傳文件的最大數(shù)量。?upload()方法也得修改, 以便一個(gè)一個(gè)地保存上傳的文件。

namespace app\models;

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

class UploadForm extends Model
{
    /**
     * @var UploadedFile[]
     */
    public $imageFiles;

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

    public function upload()
    {
        if ($this->validate()) { 
            foreach ($this->imageFiles as $file) {
                $file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
            }
            return true;
        } else {
            return false;
        }
    }
}

在視圖文件里,你需要把?multiple?選項(xiàng)添加到fileInput()函數(shù)調(diào)用里, 這樣文件輸入控件就可以接收多個(gè)文件。

<?php
use yii\widgets\ActiveForm;
?>

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

    <?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>

    <button>Submit</button>

<?php ActiveForm::end() ?>

最后,在控制器的 action 方法中,你應(yīng)該調(diào)用?UploadedFile::getInstances()?而不是?UploadedFile::getInstance()?來把UploadedFile?實(shí)例數(shù)組賦值給?UploadForm::imageFiles。

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;

class SiteController extends Controller
{
    public function actionUpload()
    {
        $model = new UploadForm();

        if (Yii::$app->request->isPost) {
            $model->imageFiles = UploadedFile::getInstances($model, 'imageFiles');
            if ($model->upload()) {
                // 文件上傳成功
                return;
            }
        }

        return $this->render('upload', ['model' => $model]);
    }
}
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)