Yii 提供 CUploadedFile 封裝上傳檔案資訊,主要屬性與方法:
| 屬性/方法 | 說明 |
|---|---|
getInstance($model, $attribute) | 取得上傳檔案實例 |
saveAs($path, $deleteTempFile=true) | 儲存至指定路徑 |
name | 原始檔名 |
tempName | 伺服器暫存路徑 |
type | MIME 類型 |
size | 檔案大小(位元組) |
error | 錯誤代碼(0=成功) |
extensionName | 副檔名 |
hasError | 是否有錯誤 |
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 的檔案。',
],
// 其他欄位規則...
];
}
}
<?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(); ?>
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]);
}
'htmlOptions' => ['enctype' => 'multipart/form-data'] 缺失會導致 $_FILES 為空。
file_1704067200_8392.jpguniqid('img_', true) . '.' . $extassets/upfile/、uploads/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); // 加浮水印
finfo_file(fopen($file->tempName, 'rb'), FILEINFO_MIME_TYPE)SetHandler default-handler / nginx: location ~ \.php$ { deny all; })Yii 的 CUploadedFile 配合 MVC 分層,提供了清晰的檔案上傳處理流程。遵循安全最佳實踐,能構建穩健可靠的上傳功能。