Uploadify 是一款基於 jQuery 的多檔案上傳外掛,支援進度條、拖曳上傳、檔案類型過濾等功能。本文示範如何在 Yii 1.x 專案中整合 Uploadify,並解決 Session ID 變更導致的驗證失效問題。
Uploadify 使用 Flash 上傳時,瀏覽器會發起新的請求,導致 Session ID 改變,造成無法讀取原有 Session 資料(如使用者 ID)。解決方案是透過前端傳遞原始 Session ID,後端以 session_id() 強制恢復。
<?php
public function actionUploadify1() {
$reinfo = 'fail';
$filename = '';
// 取得前端傳遞的原始 Session ID 並恢復
$pse = Yii::app()->request->getParam('PHPSESSION');
session_id($pse);
session_start();
$who = (int)Yii::app()->request->getParam('who');
$sjm = Yii::app()->request->getParam('sjm');
$zlsjm = Yii::app()->request->getParam('zlsjm');
// 驗證使用者身份
if ($who === Yii::app()->session['ik']) {
$tempFile = $_FILES['Filedata'];
$ext = strtolower(pathinfo($tempFile['name'], PATHINFO_EXTENSION));
// 僅允許 doc 檔案(可依需求調整)
if ($ext === 'doc') {
$targetPath = $_SERVER['DOCUMENT_ROOT'] . '/oa/upload/file/';
$scfile = date('YmdHis') . '_' . $who . '_' . md5(microtime()) . '.' . $ext;
$targetFile = str_replace('//', '/', $targetPath) . $scfile;
if (move_uploaded_file($tempFile['tmp_name'], $targetFile)) {
$relativeUrl = './upload/file/' . $scfile;
// 儲存檔案資訊至資料庫
$zlfj = new Zlfj();
$zlfj->fj_zlsjm = $zlsjm;
$zlfj->fj_uikey = Yii::app()->session['ik'];
$zlfj->fj_path = $relativeUrl;
$zlfj->fj_time = time();
$zlfj->fj_name = $tempFile['name'];
if ($zlfj->validate() && $zlfj->save()) {
$reinfo = $relativeUrl;
$filename = $tempFile['name'];
} else {
@unlink($targetFile); // 驗證失敗刪除實體檔
}
}
}
}
echo CJSON::encode(['info' => $reinfo, 'name' => $filename]);
}
?>
<script type="text/javascript">
$(function() {
var ii = 0;
$('#xceimgs2').uploadify({
'formData': {
'sjm': '<?php echo md5(time()); ?>',
'who': '<?php echo Yii::app()->session[\'ik\']; ?>',
'PHPSESSION': '<?php echo Yii::app()->session->sessionID; ?>'
},
'swf': '<?php echo JS; ?>uploadify.swf?var=' + (new Date()).getTime(),
'uploader': './index.php?r=site/uploadify1',
'buttonText': '上傳附件',
'width': '120',
'height': '26',
'fileTypeDesc': '支援的格式:',
'fileTypeExts': '*.doc',
'fileSizeLimit': '50MB',
'queueSizeLimit': 50,
'multi': true,
'onUploadStart': function(file) {
// 動態補充表單欄位
$('#xceimgs2').uploadify('settings', 'formData', {
'zlsjm': $('#juece_zlsjm').val(),
'zlikey': $('#juece_zlikey').val()
});
},
'onUploadSuccess': function(file, data, response) {
var json = eval('(' + data + ')');
if (json.info !== 'fail') {
$('#jueceim' + ii).attr('src', '<?php echo IMG . "doc.jpg"; ?>');
$('#jueceb' + ii).text(json.name);
$('#juecedele' + ii).attr('src', '<?php echo IMG . "delete2.png"; ?>');
$('#juecedele' + ii).attr('value', json.info);
ii++;
}
},
'onSelectError': function(file, errorCode, errorMsg) {
switch (errorCode) {
case -100: alert('上傳檔案數量超過限制(50個)!'); break;
case -110: alert('檔案 [' + file.name + '] 大小超過限制!'); break;
case -120: alert('檔案 [' + file.name + '] 大小異常!'); break;
case -130: alert('檔案 [' + file.name + '] 類型不正確!'); break;
}
}
});
});
</script>
PHPSESSION,後端用 session_id($pse) 恢復。此方案適用於 Yii 1.x 專案,若使用 Yii 2 請參考官方檔案上傳指南,原理相同但類別命名空間不同。