Yii2 上傳文件解析 -- 表單上傳 VS restful 上傳

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::getInstancesByName

yii\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
        )

)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淘这,一起剝皮案震驚了整個濱河市巩剖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌佳魔,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宁脊,死亡現(xiàn)場離奇詭異贤姆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)坐漏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門碧信,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人慨畸,你說我怎么就攤上這事衣式。” “怎么了碴卧?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長婶博。 經(jīng)常有香客問我荧飞,道長名党,這世上最難降的妖魔是什么挠轴? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮欧啤,結(jié)果婚禮上启上,老公的妹妹穿的比我還像新娘。我一直安慰自己冈在,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布迫靖。 她就那樣靜靜地躺著兴使,像睡著了一般。 火紅的嫁衣襯著肌膚如雪发魄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天汰寓,我揣著相機(jī)與錄音苹粟,去河邊找鬼。 笑死嵌削,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肌访。 我是一名探鬼主播艇劫,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蟹演!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起轨帜,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后毛萌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡膏秫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年缤削,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亭敢。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡帅刀,死狀恐怖扣溺,靈堂內(nèi)的尸體忽然破棺而出瓜晤,到底是詐尸還是另有隱情锥余,我是刑警寧澤痢掠,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布志群,位于F島的核電站,受9級特大地震影響锌云,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一兼贡、第九天 我趴在偏房一處隱蔽的房頂上張望娃胆。 院中可真熱鬧,春花似錦里烦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至力喷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贝咙,已是汗流浹背披蕉。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留没讲,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓徙缴,卻偏偏與公主長得像嘁信,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子潘靖,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理卦溢,服務(wù)發(fā)現(xiàn)秀又,斷路器贬芥,智...
    卡卡羅2017閱讀 134,638評論 18 139
  • 在Yii里上傳文件通常使用yii\web\UploadedFile類,它把每個上傳的文件封裝成UploadedFi...
    liudai123閱讀 1,114評論 0 0
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,778評論 6 342
  • ¥開啟¥ 【iAPP實現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程昏苏,因...
    小菜c閱讀 6,376評論 0 17
  • 紅樓夢里說:“女兒是水做的骨肉贤惯,男人是泥做的骨肉。我見了女兒救巷,我便清爽句柠;見了男子,便覺濁臭逼人溯职∶毖疲”女兒谜酒,總能觸動心...
    一滴露水閱讀 298評論 4 4