1 表單上傳 和 restful 上傳
1.1 建立一個模型 models/UploadForm.php
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* @var 單個文件上傳對應(yīng)的屬性
*/
public $single;
/**
* @var 多個文件上傳對應(yīng)的屬性
*/
public $multiple
/**
* @return array the validation rules.
*/
public function rules()
{
return [
[['single'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
[['multiple'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg','maxFiles' => 4],
];
}
}
//單個文件上傳對應(yīng)方法
public function upload()
{
if ($this->validate()) {
$newName = 'uploads/' . $this->single->baseName . '.' . $this->single->extension;
$this->single->saveAs($newName);
return true;
} else {
return false;
}
}
//多個文件上傳對應(yīng)方法
public function uploadMultiple()
{
if ($this->validate())
{
foreach ($this->multiple as $file) {
$newName = 'uploads/' . $file->baseName . '.' . $file->extension;
$file->saveAs($newName);
}
return true;
} else {
return false;
}
}
1.2 建立一個視圖文件 site/upload.php
<?php
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<div style="margin-bottom: 30px;">
<!-- 單個文件上傳按鈕,主要用于 restful -->
<input name="single-file" type="file">
<!-- 多個文件上傳按鈕,主要用于 restful -->
<input name="multi-file[]" type="file" multiple="true">
</div>
<!-- 單個文件上傳按鈕 -->
<?= $form->field($model, 'single')->fileInput() ?>
<!-- 多個文件上傳按鈕 -->
<?= $form->field($model, 'multiple[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
<button>Submit</button>
<?php ActiveForm::end() ?>
1.3 建立控制器文件 SiteController
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) {
/**
** 使用ActiveForm 上傳
**/
//獲取單個文件用 getInstance
$model->single = UploadedFile::getInstance($model, 'single');
$model->upload();
//獲取多個文件用 getInstances
$model->multiple = UploadedFile::getInstances($model, 'multiple');
$model->uploadMultiple();
unset($model->single,$model->multiple);
/**
** 使用原生文件上傳控件剃幌,主要用于 restful 文件上傳
**/
//獲取單個文件用 getInstanceByName
$model->single = UploadedFile::getInstanceByName('single-file');
$model->upload();
//獲取多個文件用 getInstancesByName
$model->multiple = UploadedFile::getInstancesByName('multi-file');
$model->uploadMultiple();
unset($model->single,$model->multiple);
}
return $this->render('upload', ['model' => $model]);
}
}
2 原理解析
2.1 代碼分析
yii\web\UploadedFile::getInstance 最終調(diào)用 yii\web\UploadedFile::getInstanceByName
yii\web\UploadedFile::getInstances 最終調(diào)用yii\web\UploadedFile::getInstancesByNameyii\web\UploadedFile::getInstanceByName | yii\web\UploadedFile::getInstancesByName 都是查找 yii\web\UploadedFile::loadFiles() 生成的 $files 數(shù)組
public static function getInstance($model, $attribute)
{
$name = Html::getInputName($model, $attribute);
return static::getInstanceByName($name);
}
public static function getInstances($model, $attribute)
{
$name = Html::getInputName($model, $attribute);
return static::getInstancesByName($name);
}
public static function getInstanceByName($name)
{
$files = self::loadFiles();
return isset($files[$name]) ? new static($files[$name]) : null;
}
public static function getInstancesByName($name)
{
$files = self::loadFiles();
if (isset($files[$name])) {
return [new static($files[$name])];
}
$results = [];
foreach ($files as $key => $file) {
if (strpos($key, "{$name}[") === 0) {
$results[] = new static($file);
}
}
return $results;
}
2.2 未經(jīng)處理的 $_FILES 數(shù)組
echo '<pre>';
print_r($_FILES);
Array
(
[single-file] => Array
(
[name] => 2017-08-01 10-11-45 的屏幕截圖.png
[type] => image/png
[tmp_name] => /tmp/php2yWOZU
[error] => 0
[size] => 203247
)
[multi-file] => Array
(
[name] => Array
(
[0] => 2017-08-01 10-11-45 的屏幕截圖.png
[1] => 2017-07-31 02-24-02 的屏幕截圖.png
)
[type] => Array
(
[0] => image/png
[1] => image/png
)
[tmp_name] => Array
(
[0] => /tmp/php40QPDr
[1] => /tmp/phpPRAVhY
)
[error] => Array
(
[0] => 0
[1] => 0
)
[size] => Array
(
[0] => 203247
[1] => 182599
)
)
[UploadForm] => Array
(
[name] => Array
(
[single] => 2017-07-30 21-35-10 的屏幕截圖.png
[multiple] => Array
(
[0] => 2017-07-28 22-20-00 的屏幕截圖.png
[1] => 2017-07-25 22-04-50 的屏幕截圖.png
)
)
[type] => Array
(
[single] => image/png
[multiple] => Array
(
[0] => image/png
[1] => image/png
)
)
[tmp_name] => Array
(
[single] => /tmp/phpCfL5Vu
[multiple] => Array
(
[0] => /tmp/phpNTGjA1
[1] => /tmp/php7EbKey
)
)
[error] => Array
(
[single] => 0
[multiple] => Array
(
[0] => 0
[1] => 0
)
)
[size] => Array
(
[single] => 150132
[multiple] => Array
(
[0] => 588277
[1] => 658391
)
)
)
)
2.3 處理過后的數(shù)組
yii\web\UploadedFile::loadFiles() 處理過后的 yii\web\UploadedFile::$_files 數(shù)組
Array
(
[single-file] => Array
(
[name] => 2017-08-01 10-11-45 的屏幕截圖.png
[tempName] => /tmp/php2yWOZU
[type] => image/png
[size] => 203247
[error] => 0
)
[multi-file[0]] => Array
(
[name] => 2017-08-01 10-11-45 的屏幕截圖.png
[tempName] => /tmp/php40QPDr
[type] => image/png
[size] => 203247
[error] => 0
)
[multi-file[1]] => Array
(
[name] => 2017-07-31 02-24-02 的屏幕截圖.png
[tempName] => /tmp/phpPRAVhY
[type] => image/png
[size] => 182599
[error] => 0
)
[UploadForm[single]] => Array
(
[name] => 2017-07-30 21-35-10 的屏幕截圖.png
[tempName] => /tmp/phpCfL5Vu
[type] => image/png
[size] => 150132
[error] => 0
)
[UploadForm[multiple][0]] => Array
(
[name] => 2017-07-28 22-20-00 的屏幕截圖.png
[tempName] => /tmp/phpNTGjA1
[type] => image/png
[size] => 588277
[error] => 0
)
[UploadForm[multiple][1]] => Array
(
[name] => 2017-07-25 22-04-50 的屏幕截圖.png
[tempName] => /tmp/php7EbKey
[type] => image/png
[size] => 658391
[error] => 0
)
)
可見 :
對于未使用ActiveForm 的 single-file抖棘, 要 獲取文件實例 使用 yii\web\UploadedFile::getInstanceByName('single-file'),
對于未使用ActiveForm 的 multiple-file切省, 要 獲取文件實例 使用 yii\web\UploadedFile::getInstancesByName('multi-file')。對于使用ActiveForm 的 single仑性, 要 獲取文件實例右蹦,使用yii\web\UploadedFile::getInstance($model, 'single');
對于使用ActiveForm 的 multiple-file, 要 獲取文件實例何陆, 使用 yii\web\UploadedFile::getInstances('multiple')
2.4 修改 actionUpload() 輸出 文件實例子
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost)
{
echo '<pre>';
//使用 ActiveForm
$model->single = UploadedFile::getInstance($model, 'single');
$model->multiple = UploadedFile::getInstances($model, 'multiple');
print_r($model->single);
print_r($model->multiple);
echo "\r\n--------------------------------------------\r\n";
//未使用 ActiveForm
$singleFile = UploadedFile::getInstanceByName('single-file');
$multipleFiles = UploadedFile::getInstancesByName('multi-file');
print_r($singleFile);
print_r($multipleFiles);
echo '</pre>';
die;
}
return $this->render('upload', ['model' => $model]);
}
2.5 獲取結(jié)果
yii\web\UploadedFile Object
(
[name] => 2017-07-30 21-35-10 的屏幕截圖.png
[tempName] => /tmp/phpwfOx2M
[type] => image/png
[size] => 150132
[error] => 0
)
Array
(
[0] => yii\web\UploadedFile Object
(
[name] => 2017-07-28 22-20-00 的屏幕截圖.png
[tempName] => /tmp/phpmkO8qv
[type] => image/png
[size] => 588277
[error] => 0
)
[1] => yii\web\UploadedFile Object
(
[name] => 2017-07-25 22-04-50 的屏幕截圖.png
[tempName] => /tmp/phpIyCVPd
[type] => image/png
[size] => 658391
[error] => 0
)
)
---------------------------------------------------------------------------------------
yii\web\UploadedFile Object
(
[name] => 2017-08-01 10-11-45 的屏幕截圖.png
[tempName] => /tmp/phpiUvdRD
[type] => image/png
[size] => 203247
[error] => 0
)
Array
(
[0] => yii\web\UploadedFile Object
(
[name] => 2017-08-01 10-11-45 的屏幕截圖.png
[tempName] => /tmp/phpUtMzfm
[type] => image/png
[size] => 203247
[error] => 0
)
[1] => yii\web\UploadedFile Object
(
[name] => 2017-07-31 02-24-02 的屏幕截圖.png
[tempName] => /tmp/phpYdi1D4
[type] => image/png
[size] => 182599
[error] => 0
)
)