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

Yii 框架圖片上傳完整教學:CUploadedFile 實作與 MVC 分層實踐

     編輯:PHP 綜合知識

CUploadedFile 類別簡介

Yii 提供 CUploadedFile 封裝上傳檔案資訊,主要屬性與方法:

屬性/方法說明
getInstance($model, $attribute)取得上傳檔案實例
saveAs($path, $deleteTempFile=true)儲存至指定路徑
name原始檔名
tempName伺服器暫存路徑
typeMIME 類型
size檔案大小(位元組)
error錯誤代碼(0=成功)
extensionName副檔名
hasError是否有錯誤

三層實作詳解

1. Model 層:驗證規則

class Link extends CActiveRecord {
    public function rules() {
        return [
            ['url', 'file',
                'allowEmpty' => true,
                'types' => 'jpg, png, gif, doc, docx, pdf, xls, xlsx, zip, rar, ppt, pptx',
                'maxSize' => 1024 * 1024 * 10, // 10MB
                'tooLarge' => '檔案超過 10MB,上傳失敗!請上傳小於 10MB 的檔案。',
            ],
            // 其他欄位規則...
        ];
    }
}

2. View 層:上傳表單

<?php
$form = $this->beginWidget('CActiveForm', [
    'id' => 'link-form',
    'enableAjaxValidation' => false,
    'htmlOptions' => ['enctype' => 'multipart/form-data'], // 關鍵!
]);
?>

<div class="row">
    <?php echo $form->labelEx($model, 'url'); ?>
    <?php echo CHtml::activeFileField($model, 'url'); ?>
    <?php echo $form->error($model, 'url'); ?>
</div>

<?php $this->endWidget(); ?>

3. Controller 層:處理上傳與儲存

public function actionCreate() {
    $model = new Link();

    if (isset($_POST['Link'])) {
        $model->attributes = $_POST['Link'];

        // 若未填寫名稱,使用檔名
        if (empty($_POST['Link']['name'])) {
            $model->name = $model->url; // 此時 $model->url 尚為 CUploadedFile 物件,需調整邏輯
        }

        // 取得上傳檔案實例
        $file = CUploadedFile::getInstance($model, 'url');

        // 產生唯一儲存檔名
        if ($file instanceof CUploadedFile && !$file->hasError) {
            $ext = $file->extensionName;
            $fileName = 'file_' . time() . '_' . rand(1000, 9999) . '.' . $ext;
            $savePath = Yii::app()->basePath . '/../assets/upfile/' . $fileName;
            $model->url = $savePath; // Model 儲存相對或絕對路徑
        } else {
            $model->url = Yii::app()->basePath . '/../assets/upfile/noPic.jpg'; // 預設圖
        }

        if ($model->save()) {
            // Model 存入 DB 成功後,再實際搬移檔案
            if ($file instanceof CUploadedFile && !$file->hasError) {
                $file->saveAs($model->url);
            }
            $this->redirect(['view', 'id' => $model->lid]);
        }
    }

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

關鍵細節與最佳實踐

表單 enctype 必須設定

'htmlOptions' => ['enctype' => 'multipart/form-data'] 缺失會導致 $_FILES 為空。

檔案命名策略

  • 時間戳 + 隨機數 + 原始副檔名:file_1704067200_8392.jpg
  • 或使用 UUID:uniqid('img_', true) . '.' . $ext
  • 避免直接使用用戶檔名(安全性、重名、特殊字元問題)。

儲存路徑建議

  • Web 可存取目錄:assets/upfile/、uploads/
  • 生產環境建議:雲端儲存(AWS S3、阿里云 OSS、七牛雲)+ CDN 加速。
  • 目錄權限:chmod 755、擁有者為 Web 使用者(www-data/nginx)。

錯誤處理與使用者回饋

if ($file->hasError) {
    switch ($file->error) {
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            $model->addError('url', '檔案大小超過限制');
            break;
        case UPLOAD_ERR_PARTIAL:
            $model->addError('url', '檔案上傳不完整');
            break;
        case UPLOAD_ERR_NO_FILE:
            // 允許為空時不視為錯誤
            break;
        default:
            $model->addError('url', '上傳失敗,錯誤代碼:' . $file->error);
    }
}

多檔案上傳

// View
echo CHtml::activeFileField($model, 'files[]', ['multiple' => true]);

// Controller
$files = CUploadedFile::getInstances($model, 'files');
foreach ($files as $file) {
    // 處理每個檔案...
}

進階:圖片處理整合

上傳後可串接縮圖、水印、格式轉換:

// 使用 Intervention Image (需 composer 安裝)
use Intervention\Image\Facades\Image;

$img = Image::make($file->tempName);
$img->fit(800, 600)->save($savePath); // 縮放並裁切
$img->insert('watermark.png', 'bottom-right', 10, 10)->save($savePath); // 加浮水印

安全性檢查清單

  1. MIME 類型二次驗證:finfo_file(fopen($file->tempName, 'rb'), FILEINFO_MIME_TYPE)
  2. 副檔名白名單驗證
  3. 檔案大小限制(PHP.ini + 程式碼雙重)
  4. 上傳目錄禁止腳本執行(.htaccess: SetHandler default-handler / nginx: location ~ \.php$ { deny all; })
  5. 檔案內容掃描(ClamAV、VirusTotal API)
  6. CSRF Token 驗證

Yii 的 CUploadedFile 配合 MVC 分層,提供了清晰的檔案上傳處理流程。遵循安全最佳實踐,能構建穩健可靠的上傳功能。

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