首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Yii2 文件上傳實戰:基於 UploadedFile 組件的完整實現流程

     編輯:PHP 綜合知識

三層架構實現

1. Model 層 - backend\models\Upload.php

namespace backend\models;
use Yii;
use yii\web\UploadedFile;

class Upload extends \yii\db\ActiveRecord {
    public $file;  // 非數據庫字段,接收上傳文件對象
    
    public function rules() {
        return [
            [['file'], 'file'],  // 文件驗證規則
        ];
    }
}

關鍵點:$file 定義為公共屬性而非數據庫字段,驗證規則使用 'file' 核心驗證器,自動檢查擴展名、MIME 類型、大小等。

2. View 層 - 表單渲染

use yii\widgets\ActiveForm;

$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]);
echo $form->field($model, 'file')->fileInput();
echo '<button>Submit</button>';
ActiveForm::end();

⚠️ **必須設置** enctype="multipart/form-data",否則 $_FILES 為空。

3. Controller 層 - backend\controllers\ToolsController.php

namespace backend\controllers;
use backend\models\Upload;
use yii\web\UploadedFile;

class ToolsController extends \yii\web\Controller {
    public function actionUpload() {
        $model = new Upload();
        $uploadSuccessPath = '';
        
        if (Yii::$app->request->isPost) {
            // 關鍵:獲取上傳文件對象
            $model->file = UploadedFile::getInstance($model, 'file');
            
            // 目標目錄:/public/uploads/YYYYMMDD/
            $dir = "../../public/uploads/" . date("Ymd");
            if (!is_dir($dir)) mkdir($dir, 0755, true);
            
            if ($model->validate()) {
                // 生成唯一文件名:時分秒毫秒 + 原文件名 + 擴展名
                $fileName = date("His") . $model->file->baseName . '.' . $model->file->extension;
                $savePath = $dir . '/' . $fileName;
                
                // 核心:保存文件
                $model->file->saveAs($savePath);
                
                // 返回相對路徑供前端展示
                $uploadSuccessPath = "/uploads/" . date("Ymd") . "/" . $fileName;
            }
        }
        
        return $this->render('upload', [
            'model' => $model,
            'uploadSuccessPath' => $uploadSuccessPath,
        ]);
    }
}

UploadedFile 核心屬性與方法

屬性/方法說明
name客戶端原始文件名
baseName不含擴展名的文件名
extension文件擴展名 (小寫)
tempName服務器臨時文件路徑
size文件大小 (字節)
typeMIME 類型
saveAs($path)移動臨時文件到目標路徑
getInstance($model, $attribute)從模型屬性獲取上傳文件對象
getInstances($model, $attribute)多文件上傳獲取數組

常見驗證規則擴展

public function rules() {
    return [
        [['file'], 'file', 
            'extensions' => ['jpg', 'png', 'gif'],  // 允許擴展名
            'mimeTypes' => ['image/jpeg', 'image/png', 'image/gif'], // MIME 白名單
            'maxSize' => 1024 * 1024 * 5,           // 5MB 限制
            'minSize' => 1024,                       // 1KB 最小
            'checkExtensionByMimeType' => true,      // 雙重驗證
        ],
    ];
}

安全最佳實踐

  1. 文件名安全:使用時間戳/UUID/哈希重命名,防止路徑遍歷、覆蓋、腳本注入
  2. 類型驗證:同時檢查擴展名、MIME 類型、文件頭魔數
  3. 存儲隔離:上傳目錄設置為不可執行 (Nginx location ~ \.php$ { deny all; })
  4. 病毒掃描:集成 ClamAV 異步掃描
  5. 大小限制:PHP upload_max_filesize、Nginx client_max_body_size 雙重限制

多文件上傳擴展

// Model
public $files;  // 複數
public function rules() {
    return [ [['files'], 'file', 'maxFiles' => 10] ];
}

// Controller
$model->files = UploadedFile::getInstances($model, 'files');
foreach ($model->files as $file) {
    $file->saveAs($path . '/' . $file->baseName . '.' . $file->extension);
}

總結

Yii2 UploadedFile 組件封裝了 PHP 原生 $_FILES 處理,提供物件化 API、內建驗證器、安全文件移動。配合 ActiveForm、ActiveRecord 可快速構建安全可靠的上傳功能。實際項目中建議封裝為通用上傳 Service,統一處理存儲策略(本地/雲存儲)、CDN 同步、圖片處理(縮略圖/水印)等橫切關注點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved