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

CKEditor 4 整合 PHP 圖片上傳完整實作:配置、伺服端驗證、回調協議

     編輯:PHP 綜合知識

前言:CKEditor 圖片上傳架構

CKEditor 透過 filebrowserImageUploadUrl 指定上傳端點。上傳完成後,伺服器必須回傳特定 JavaScript 片段呼叫 window.parent.CKEDITOR.tools.callFunction() 通知編輯器插入圖片。

步驟一:前端配置 config.js

CKEDITOR.editorConfig = function(config) {
    // 圖片上傳端點
    config.filebrowserImageUploadUrl = '/upload.php?type=img';
    // 影音上傳端點 (可選)
    config.filebrowserFlashUploadUrl = '/upload.php?type=flash';
    
    // 可選:檔案瀏覽器 (瀏覽伺服器圖片)
    // config.filebrowserBrowseUrl = '/browser.php';
};

步驟二:伺服端完整實作 upload.php

<?php
/**
 * CKEditor 檔案上傳處理器
 * 回傳格式:
 */

// 配置區
$config = [
    'allowed_types' => ['img', 'flash'],
    'img' => ['ext' => ['jpg','jpeg','png','gif','bmp','webp'], 'max_size' => 2 * 1024 * 1024], // 2MB
    'flash' => ['ext' => ['flv','swf','mp4'], 'max_size' => 50 * 1024 * 1024], // 50MB
    'upload_dir' => [
        'img' => __DIR__ . '/uploads/images',
        'flash' => __DIR__ . '/uploads/flash',
    ],
    'url_prefix' => '/uploads', // 公開訪問 URL 前綴
    'filename_generator' => function($ext) {
        // 命名規則:時間戳_隨機數.副檔名
        return date('YmdHis') . '_' . mt_rand(1000, 9999) . '.' . $ext;
    },
];

// 確保上傳目錄存在
foreach ($config['upload_dir'] as $dir) {
    if (!is_dir($dir)) mkdir($dir, 0755, true);
}

// 輸出 JS 回調並結束
function ckResponse($funcNum, $url = '', $message = '') {
    header('Content-Type: text/html; charset=utf-8');
    $url = addslashes($url);
    $message = addslashes($message);
    echo "<script>window.parent.CKEDITOR.tools.callFunction($funcNum, '$url', '$message');</script>";
    exit;
}

// 1. 驗證 CKEditor 功能編號
$funcNum = (int)($_GET['CKEditorFuncNum'] ?? 0);
if (!$funcNum) ckResponse(0, '', '錯誤的功能調用請求 (缺少 CKEditorFuncNum)');

// 2. 驗證類型參數
$type = $_GET['type'] ?? '';
if (!in_array($type, $config['allowed_types'])) {
    ckResponse($funcNum, '', '不支援的上傳類型: ' . htmlspecialchars($type));
}

$cfg = $config[$type];
$uploadDir = $config['upload_dir'][$type];

// 3. 檢查檔案上傳
if (!isset($_FILES['upload']) || $_FILES['upload']['error'] !== UPLOAD_ERR_OK) {
    ckResponse($funcNum, '', '檔案上傳失敗,錯誤代碼: ' . ($_FILES['upload']['error'] ?? '未知'));
}

$file = $_FILES['upload'];

// 4. 驗證副檔名
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $cfg['ext'])) {
    ckResponse($funcNum, '', '不允許的檔案類型: .' . $ext . '。允許: ' . implode(', ', $cfg['ext']));
}

// 5. 驗證檔案大小
if ($file['size'] > $cfg['max_size']) {
    ckResponse($funcNum, '', '檔案過大: ' . round($file['size']/1024, 1) . 'KB。限制: ' . round($cfg['max_size']/1024, 1) . 'KB');
}

// 6. 驗證 MIME 類型 (防偽裝)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);

$allowedMimes = [
    'img' => ['image/jpeg','image/png','image/gif','image/bmp','image/webp'],
    'flash' => ['video/x-flv','application/x-shockwave-flash','video/mp4'],
];
if (!in_array($mime, $allowedMimes[$type])) {
    ckResponse($funcNum, '', '檔案內容類型不符: ' . $mime);
}

// 7. 生成檔名並移動
$filename = $config['filename_generator']($ext);
$destPath = $uploadDir . '/' . $filename;
$publicUrl = $config['url_prefix'] . '/' . ($type === 'img' ? 'images' : 'flash') . '/' . $filename;

if (!move_uploaded_file($file['tmp_name'], $destPath)) {
    ckResponse($funcNum, '', '檔案儲存失敗,請檢查目錄權限');
}

// 8. 成功回調
ckResponse($funcNum, $publicUrl, '上傳成功');

關鍵安全強化

防護層實作
副檔名白名單嚴格限制允許的擴展名
MIME 類型驗證finfo_file() 檢測真實內容,防止偽裝副檔名
檔案大小限制配置 max_size,配合 php.ini upload_max_filesize
隨機檔名時間戳+隨機數,防覆蓋、防猜測、防注入
儲存目錄非公開執行上傳目錄設定 php_flag engine off 或放在 public 外
圖片重新處理可選:imagecreatefromstring() 重新編碼,剝離 EXIF/惡意代碼
CSRF Token生產環境建議驗證 Token

進階:圖片自動縮圖/水印


// 在 move_uploaded_file 成功後
if ($type === 'img') {
    $img = @imagecreatefromstring(file_get_contents($destPath));
    if ($img) {
        // 限制最大寬度 1200px
        $w = imagesx($img); $h = imagesy($img);
        if ($w > 1200) {
            $newH = intval($h * 1200 / $w);
            $thumb = imagescale($img, 1200, $newH);
            imagejpeg($thumb, $destPath, 85);
            imagedestroy($thumb);
        }
        imagedestroy($img);
    }
}

CKEditor 5 差異說明

CKEditor 5 使用 **Simple Upload Adapter**,回傳格式為 JSON:


// CKEditor 5 期望回傳
header('Content-Type: application/json');
echo json_encode([
    'url' => $publicUrl,
    // 可選
    'width' => 800,
    'height' => 600,
]);

若同時支援 CKEditor 4/5,可根據 $_GET['CKEditor'] 或 Accept 標頭判斷回傳格式。

結語

CKEditor 圖片上傳核心在於**伺服端嚴格驗證**與**標準回調協議**。本文提供的 upload.php 涵蓋:類型白名單、MIME 檢測、大小限制、隨機命名、安全儲存、標準 JS 回調,可直接用於生產環境。記得配合 Nginx/Apache 禁用上傳目錄腳本執行權限,構建完整防禦纵深。

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