CKEditor 是功能強大的所見即所得編輯器,但預設不含圖片上傳功能,需搭配官方檔案管理器 CKFinder。本文詳述 PHP 環境下的安裝、配置、權限控管與前後端整合步驟。
/project-root/
├── admin/
│ ├── ckeditor/ # CKEditor 核心
│ │ ├── ckeditor.js
│ │ ├── config.js
│ │ ├── styles.js
│ │ └── plugins/...
│ ├── ckfinder/ # CKFinder 核心 (與 ckeditor 同級)
│ │ ├── ckfinder.php
│ │ ├── config.php
│ │ ├── core/connector/php/connector.php
│ │ └── userfiles/ # 上傳檔案儲存目錄 (需寫入權限)
│ └── edit.php # 使用編輯器的頁面
└── public/ # 公開可存取目錄
└── uploads/ # 實際對外可訪問的上傳目錄 (符號連結或實體目錄)
/admin/ckeditor/// /admin/ckeditor/config.js
CKEDITOR.editorConfig = function(config) {
config.language = 'zh-cn'; // 介面語言
config.uiColor = '#F7F7F7'; // 工具列顏色
config.height = 400; // 編輯區高度
config.toolbar = 'Full'; // 工具列組合
config.toolbar_Full = [
{ name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview', 'Print', '-', 'Templates'] },
{ name: 'clipboard', items: ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'] },
{ name: 'editing', items: ['Find', 'Replace', '-', 'SelectAll'] },
{ name: 'forms', items: ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'] },
'/',
{ name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat'] },
{ name: 'paragraph', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl'] },
{ name: 'links', items: ['Link', 'Unlink', 'Anchor'] },
{ name: 'insert', items: ['Image', 'Flash', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak', 'Iframe'] },
'/',
{ name: 'styles', items: ['Styles', 'Format', 'Font', 'FontSize'] },
{ name: 'colors', items: ['TextColor', 'BGColor'] },
{ name: 'tools', items: ['Maximize', 'ShowBlocks'] },
{ name: 'about', items: ['About'] }
];
};
/admin/ckfinder/ (與 ckeditor 同級)<?php
// /admin/ckfinder/config.php
$config = [];
// 【安全關鍵】認證函式:必須返回 true 才允許上傳/瀏覽
$config['authentication'] = function () {
// 方案 A: 簡單 Session 驗證 (需在登入系統中設定 $_SESSION['is_admin'] = true)
return isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true;
// 方案 B: 整合現有 ACL 權限系統
// return MyAuth::checkPermission('ckfinder_access');
// ⚠️ 絕對不要直接 return true (生產環境極度危險)
};
// 【儲存路徑】上傳檔案的實體目錄 (需 Web 伺服器寫入權限)
// 建議放在 public 目錄下,並設定符號連結或直接指向
$config['backends'][] = [
'name' => 'default',
'adapter' => 'local',
'baseUrl' => '/public/uploads/', // 公開可訪問的 URL 前綴
'root' => '/var/www/project/public/uploads/', // 實體絕對路徑 (根據實際環境修改)
'chmodFiles' => 0644,
'chmodFolders' => 0755,
'filesystemEncoding' => 'UTF-8',
];
// 其他常用設定
$config['defaultResourceTypes'] = 'Images,Files,Flash';
$config['htmlExtensions'] = ['html', 'htm', 'xml', 'js'];
$config['hideFolders'] = ['.git', 'CVS', '.svn'];
$config['hideFiles'] = ['.htaccess', 'web.config'];
$config['forceAscii'] = false; // 允許中文檔名
$config['secureImageUploads'] = true; // 驗證圖片檔頭防偽裝上傳
$config['checkSizeAfterScaling'] = true;
$config['maxImageSize'] = 0; // 不限制圖片尺寸
$config['thumbnails'] = [
'url' => '/public/uploads/.thumbs/', // 縮圖 URL
'directory' => '/var/www/project/public/uploads/.thumbs/', // 縮圖實體目錄
'enabled' => true,
'maxWidth' => 100,
'maxHeight' => 100,
'quality' => 80,
];
return $config;
?>
chown -R www-data:www-data /var/www/project/public/uploads
chmod -R 755 /var/www/project/public/uploads
# 或使用 ACL 更精細控制
setfacl -R -m u:www-data:rwx /var/www/project/public/uploads
<?php
// /admin/edit.php
require_once __DIR__ . '/ckeditor/ckeditor.php';
require_once __DIR__ . '/ckfinder/ckfinder.php';
$CKEditor = new CKEditor();
$CKEditor->basePath = '/admin/ckeditor/';
$CKEditor->returnOutput = true;
// 關鍵:整合 CKFinder
CKFinder::SetupCKEditor($CKEditor, '/admin/ckfinder/'); // 相對於網站根目錄
// 初始內容 (來自資料庫)
$initialContent = '<p>歡迎使用 CKEditor + CKFinder</p>';
// 輸出編輯器 HTML
$editorHtml = $CKEditor->editor('content', $initialContent, ['id' => 'editor1']);
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>編輯文章</title></head>
<body>
<form method="post" action="save.php">
<?php echo $editorHtml; ?>
<button type="submit">儲存</button>
</form>
</body></html>
<!-- 引入 CKEditor -->
<script src="/admin/ckeditor/ckeditor.js"></script>
<!-- 引入 CKFinder -->
<script src="/admin/ckfinder/ckfinder.js"></script>
<textarea name="content" id="editor1"></textarea>
<script>
CKEDITOR.replace('editor1', {
// CKFinder 整合設定
filebrowserBrowseUrl: '/admin/ckfinder/ckfinder.html',
filebrowserImageBrowseUrl: '/admin/ckfinder/ckfinder.html?type=Images',
filebrowserFlashBrowseUrl: '/admin/ckfinder/ckfinder.html?type=Flash',
filebrowserUploadUrl: '/admin/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files',
filebrowserImageUploadUrl: '/admin/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images',
filebrowserFlashUploadUrl: '/admin/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Flash'
});
</script>
| 問題 | 原因與解決 |
|---|---|
| 點選圖片圖示無反應 / 404 | filebrowserBrowseUrl 路徑錯誤。檢查瀏覽器網路面板請求 URL,確認 CKFinder 入口檔案可存取。 |
| 上傳後圖片顯示斷圖 | baseUrl 與實際公開 URL 不符。確認 config.php 中 baseUrl 對應的目錄可經由瀏覽器直接訪問。 |
| 上傳失敗 "Invalid CSRF Token" | CKFinder 3 預設啟用 CSRF 保護。確認表單包含 <input type="hidden" name="CKFinder_CSRF_Token" value="..."> 或在 AJAX 請求中帶上 Header。 |
| 中文檔名亂碼 | 設定 forceAscii = false,確保檔案系統、PHP、資料庫皆為 UTF-8。 |
| 權限不足無法寫入 | Web 伺服器進程 (www-data/apache/nginx) 對 root 目錄無寫入權限。檢查 chown/chmod/SELinux/AppArmor。 |
secureImageUploads 驗證圖片檔頭。config.php 設定 maxFileSize,並在 PHP upload_max_filesize/post_max_size 同步調整。php_flag engine off (Apache) 或 location ~ \.php$ { deny all; } (Nginx) 禁止腳本執行。