CKEditor 作為主流富文本編輯器,其文件上傳功能默認配置往往無法滿足生產環境需求。本文系統講解如何實現上傳文件按年月分目錄存儲、隨機重命名防衝突、中文文件名亂碼解決,以及服務端圖片水印添加的完整集成方案。
修改 editor/filemanager/connectors/php/config.php:
<?php
// 原配置
$Config['UserFilesPath'] = '/userfiles/';
// 修改為按年月分目錄
$Config['UserFilesPath'] = '/uploadfiles/' . date("Ym") . "/";
// 同步修改物理路徑
$Config['UserFilesAbsolutePath'] = $_SERVER['DOCUMENT_ROOT'] . $Config['UserFilesPath'];
?>
效果:上傳文件自動存入 /uploadfiles/202401/ 等目錄,便於管理與性能優化。
修改 editor/filemanager/connectors/php/io.php 中的 SanitizeFileName 函數:
<?php
function SanitizeFileName($sNewFileName) {
global $Config;
$sNewFileName = stripslashes($sNewFileName);
// 保留最後一個點號作為擴展名分隔
if ($Config['ForceSingleExtension']) {
$sNewFileName = preg_replace('/\.(?![^.]*$)/', '_', $sNewFileName);
}
// 移除危險字符
$sNewFileName = preg_replace('/[\\\|\/|\:|\?|\*|"|<|>]/', '_', $sNewFileName);
// 核心:生成唯一文件名
$sExtension = substr($sNewFileName, strrpos($sNewFileName, '.') + 1);
$sNewFileName = my_setfilename() . '.' . $sExtension;
return $sNewFileName;
}
function my_setfilename() {
$gettime = explode(' ', microtime());
$string = 'abcdefghijklmnopqrstuvwxyz0123456789';
$rand = '';
for ($x = 0; $x < 12; $x++) {
$rand .= substr($string, mt_rand(0, strlen($string) - 1), 1);
}
// 格式:年月日時分秒 + 微秒後6位 + 12位隨機字符
return date("ymdHis") . substr($gettime[0], 2, 6) . $rand;
}
?>
命名規則示例: 240115143022_123456_a1b2c3d4e5f6.jpg,極低衝突概率。
修改 editor/filemanager/connectors/php/commands.php 中 FileUpload 函數:
<?php
// 在獲取擴展名後添加
$sExtension = substr($sFileName, (strrpos($sFileName, '.') + 1));
$sExtension = strtolower($sExtension);
// 重命名邏輯
$sFileName = rand(0, 100) . "." . $sExtension; // 可替換為更複雜的命名策略
// 或使用 iconv 解決中文亂碼(不解決重名)
// $sFileName = iconv("UTF-8", "GBK", $sFileName);
?>
<?php
/**
* 給圖片添加水印
* @param string $imgSrc 目標圖片路徑
* @param string $markImg 水印圖片路徑(圖片模式時)
* @param string $markText 水印文字(文字模式時)
* @param string $TextColor 文字顏色 RGB,如 "255,0,0"
* @param int $markPos 位置 0-9(0=隨機,1-9=九宮格)
* @param string $fontType 字體文件路徑(文字模式必需)
* @param string $markType 'img' 或 'text'
*/
function setWater($imgSrc, $markImg, $markText, $TextColor, $markPos, $fontType, $markType) {
$srcInfo = @getimagesize($imgSrc);
if (!$srcInfo) return;
$srcImg_w = $srcInfo[0];
$srcImg_h = $srcInfo[1];
// 創建源圖像資源
switch ($srcInfo[2]) {
case 1: $srcim = imagecreatefromgif($imgSrc); break;
case 2: $srcim = imagecreatefromjpeg($imgSrc); break;
case 3: $srcim = imagecreatefrompng($imgSrc); break;
default: die("不支持的圖片類型");
}
// 處理水印圖片
if ($markType == "img") {
if (!file_exists($markImg) || empty($markImg)) return;
$markImgInfo = @getimagesize($markImg);
if ($srcImg_w < $markImgInfo[0] || $srcImg_h < $markImgInfo[1]) return;
switch ($markImgInfo[2]) {
case 1: $markim = imagecreatefromgif($markImg); break;
case 2: $markim = imagecreatefromjpeg($markImg); break;
case 3: $markim = imagecreatefrompng($markImg); break;
default: die("不支持的水印圖片類型");
}
$logow = $markImgInfo[0];
$logoh = $markImgInfo[1];
}
// 處理水印文字
if ($markType == "text") {
$fontSize = 16;
if (empty($markText) || !file_exists($fontType)) return;
$box = @imagettfbbox($fontSize, 0, $fontType, $markText);
$logow = max($box[2], $box[4]) - min($box[0], $box[6]);
$logoh = max($box[1], $box[3]) - min($box[5], $box[7]);
}
// 計算水印位置(九宮格)
if ($markPos == 0) $markPos = rand(1, 9);
switch ($markPos) {
case 1: $x = 5; $y = 5; break; // 左上
case 2: $x = ($srcImg_w - $logow) / 2; $y = 5; break; // 上中
case 3: $x = $srcImg_w - $logow - 5; $y = 5; break; // 右上
case 4: $x = 5; $y = ($srcImg_h - $logoh) / 2; break; // 左中
case 5: $x = ($srcImg_w - $logow) / 2; $y = ($srcImg_h - $logoh) / 2; break; // 中心
case 6: $x = $srcImg_w - $logow - 5; $y = ($srcImg_h - $logoh) / 2; break; // 右中
case 7: $x = 5; $y = $srcImg_h - $logoh - 5; break; // 左下
case 8: $x = ($srcImg_w - $logow) / 2; $y = $srcImg_h - $logoh - 5; break; // 下中
case 9: $x = $srcImg_w - $logow - 5; $y = $srcImg_h - $logoh - 5; break; // 右下
default: die("不支持的位置");
}
// 創建目標畫布並合成
$dst_img = @imagecreatetruecolor($srcImg_w, $srcImg_h);
imagecopy($dst_img, $srcim, 0, 0, 0, 0, $srcImg_w, $srcImg_h);
if ($markType == "img") {
imagecopy($dst_img, $markim, $x, $y, 0, 0, $logow, $logoh);
imagedestroy($markim);
}
if ($markType == "text") {
$rgb = explode(',', $TextColor);
$color = imagecolorallocate($dst_img, $rgb[0], $rgb[1], $rgb[2]);
imagettftext($dst_img, $fontSize, 0, $x, $y, $color, $fontType, $markText);
}
// 保存覆蓋原圖
switch ($srcInfo[2]) {
case 1: imagegif($dst_img, $imgSrc); break;
case 2: imagejpeg($dst_img, $imgSrc, 90); break; // 可設置質量
case 3: imagepng($dst_img, $imgSrc); break;
}
imagedestroy($dst_img);
imagedestroy($srcim);
}
?>
在 commands.php 的 FileUpload 函數中,文件保存成功後調用:
<?php
// 圖片水印集成示例
if (in_array(strtolower($sExtension), ['jpg', 'jpeg', 'png', 'gif'])) {
$uploadedFile = $Config['UserFilesAbsolutePath'] . $sFileName;
// 圖片水印模式
setWater($uploadedFile, 'mark/logo.png', '', '', 9, '', 'img');
// 或文字水印模式
// setWater($uploadedFile, '', '© MySite.com', '255,255,255', 5, '/fonts/simhei.ttf', 'text');
}
?>
php_gd2 擴展,文字水印額外需 freetype 支持imagecreatetruecolor 創建黑色背景,PNG/GIF 透明圖需額外處理透明通道755 + 所有者 www-data)通過以上配置,可構建企業級的 CKEditor 文件上傳系統,滿足歸檔管理、版權保護、安全合規等多重需求。