?
このドキュメントでは、 php中國語ネットマニュアル リリース
在Yii里上傳文件通常使用yii\web\UploadedFile類, 它把每個(gè)上傳的文件封裝成?UploadedFile
?對象。 結(jié)合yii\widgets\ActiveForm和models,你可以輕松實(shí)現(xiàn)安全的上傳文件機(jī)制。
和普通的文本輸入框類似,當(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{
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í)例。它對應(yīng)一條file
?驗(yàn)證規(guī)則, 該規(guī)則使用 yii\validators\FileValidator 來確保只上傳擴(kuò)展名為?png
?或?jpg
?的文件。?upload()
?方法會執(zhí)行該驗(yàn)證并且把上傳的文件保存在服務(wù)器上。
通過?file
?驗(yàn)證器,你可以檢查文件的擴(kuò)展名,大小,MIME類型等等。詳情請查閱?Core Validatators?章節(jié)。
>提示: 如果你要上傳的是一張圖片,可以考慮使用image
驗(yàn)證器。?image
?驗(yàn)證器是通過yii\validators\ImageValidator實(shí)現(xiàn)驗(yàn)證的,確保對應(yīng)的模型屬性 收到的文件是有效的圖片文件,然后才保存,或者使用擴(kuò)展類Imagine Extension進(jìn)行處理.
接下來,在視圖里創(chuàng)建一個(gè)文件輸入控件
<?phpuse 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()
?方法會渲染一個(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ù)器上。
將前面所述的代碼做一些調(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{
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è)文件。
<?phpuse yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image
? ? public?$filename;
? ?
? ? public?$key;
? ?
? ? protected?$fileObject;?//?SplFileObject?is?very?convenient?for?seeking?to?particular?line?in?a?file
? ?
? ? public?function?init()
? ? {
? ? ? ? parent::init();
? ? ? ? //?open?file
? ? ? ? $this->fileObject?=?new?SplFileObject($this->filename);
? ? }
? ?
? ? protected?function?prepareModels()
? ? {
? ? ? ? $models?=?[];
? ? ? ? $pagination?=?$this->getPagination();
? ? ? ? if?($pagination?===?false)?{
? ? ? ? ? ? //?in?case?there's?no?pagination,?read?all?lines
? ? ? ? ? ? while?(!$this->fileObject->eof())?{
? ? ? ? ? ? ? ? $models[]?=?$this->fileObject->fgetcsv();
? ? ? ? ? ? ? ? $this->fileObject->next();
? ? ? ? ? ? }
? ? ? ? }?else?{
? ? ? ? ? ? //?in?case?there's?pagination,?read?only?a?single?page
? ? ? ? ? ? $pagination->totalCount?=?$this->getTotalCount();
? ? ? ? ? ? $this->fileObject->seek($pagination->getOffset());
? ? ? ? ? ? $limit?=?$pagination->getLimit();
? ? ? ? ? ? for?($count?=?0;?$count?<?$limit;?++$count)?{
? ? ? ? ? ? ? ? $models[]?=?$this->fileObject->fgetcsv();
? ? ? ? ? ? ? ? $this->fileObject->next();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return?$models;
? ? }
? ?
? ? protected?function?prepareKeys($models)
? ? {
? ? ? ? if?($this->key?!==?null)?{
? ? ? ? ? ? $keys?=?[];
? ? ? ? ? ? foreach?($models?as?$model)?{
? ? ? ? ? ? ? ? if?(is_string($this->key))?{
? ? ? ? ? ? ? ? ? ? $keys[]?=?$model[$this->key];
? ? ? ? ? ? ? ? }?else?{
? ? ? ? ? ? ? ? ? ? $keys[]?=?call_user_func($this->key,?$model);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return?$keys;
? ? ? ? }?else?{
? ? ? ? ? ? return?array_keys($models);
? ? ? ? }
? ? }
? ?
? ? protected?function?prepareTotalCount()
? ? {
? ? ? ? $count?=?0;
? ? ? ? while?(!$this->fileObject->eof())?{
? ? ? ? ? ? $this->fileObject->next();
? ? ? ? ? ? ++$count;
? ? ? ? }
? ? ? ? return?$count;
? ? }
}