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

.NET 整合 UEditor 富文本編輯器:安裝、配置、後端處理完整指南

     編輯:ASP.NET 基礎

前言

UEditor 是百度開源的富文本編輯器,.NET 版本透過 Uploader.ashx 處理上傳。本文涵蓋:專案整合步驟、前端初始化、後端配置、上傳路徑自訂、安全性設定、常見坑點,適用於 ASP.NET WebForms 與 MVC。

1. 專案結構與檔案部署

YourProject/
├── Ueditor/                    # 編輯器核心資源
│   ├── editor_all.js
│   ├── editor_config.js
│   ├── themes/default/ueditor.css
│   ├── net/
│   │   ├── Uploader.cs         # 核心上傳處理
│   │   └── Config/             # 配置類別
│   ├── fileUp.ashx             # 檔案上傳端點
│   ├── imageUp.ashx            # 圖片上傳端點
│   ├── scrawlUp.ashx           # 塗鴉上傳端點
│   └── ...其他 .ashx
├── Uploads/                    # 上傳儲存目錄(需寫入權限)
│   ├── image/
│   ├── file/
│   └── video/
└── Web.config / appsettings.json

2. 前端頁面引用與初始化

.aspx / .cshtml 共用標記


<!-- 1. 引入樣式與腳本 -->
<link href="Ueditor/themes/default/ueditor.css" rel="stylesheet" />
<script src="Ueditor/editor_config.js"></script>
<script src="Ueditor/editor_all.js"></script>

<!-- 2. 編輯器容器(建議 textarea)-->
<textarea id="txtContent" name="txtContent" runat="server" style="width:100%;height:400px;">
    <p>初始內容...</p>
</textarea>

<!-- 3. 實例化 -->
<script type="text/javascript">
    // 方式 A:傳統實例化 (UEditor 1.2.4+)
    var ue = UE.getEditor('txtContent', {
        initialFrameWidth: '100%',
        initialFrameHeight: 400,
        toolbars: [[
            'fullscreen', 'source', '|', 'undo', 'redo', '|',
            'bold', 'italic', 'underline', 'strikethrough', '|',
            'forecolor', 'backcolor', '|',
            'justifyleft', 'justifycenter', 'justifyright', '|',
            'insertorderedlist', 'insertunorderedlist', '|',
            'link', 'unlink', '|', 'image', 'video', 'attachment', '|',
            'table', 'simpleupload'
        ]]
    });

    // 方式 B:簡化實例化 (自動綁定同 id textarea)
    // UE.getEditor('txtContent');
</script>

<!-- 4. 提交按鈕 -->
<input type="submit" value="送出" />

關鍵點:為何用 <textarea> 而非 <div>?

  • textarea 原生支援表單提交,Request.Form["txtContent"] 直接取得 HTML 內容。
  • div 需手動同步隱藏欄位,易遺漏導致後端取不到值。
  • 官方文件雖提及 <script type="text/plain" id="editor">,但 .NET 版配合 textarea 最穩定。

3. 後端配置:editor_config.js


// Ueditor/editor_config.js
window.UEDITOR_HOME_URL = "/Ueditor/"; // 網站根目錄下的 Ueditor 資料夾

window.UEDITOR_CONFIG = {
    // 後端統一處理端點 (UEditor 1.4.3+ 採用單一 controller)
    serverUrl: "/Ueditor/net/Uploader.ashx", 

    // 圖片上傳
    imageActionName: "uploadimage",
    imageFieldName: "upfile",
    imageMaxSize: 2048000,        // 2MB
    imageAllowFiles: [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp"],
    imageCompressEnable: true,
    imageCompressBorder: 1600,
    imageInsertAlign: "none",
    imageUrlPrefix: "",           // 圖片 URL 前綴(如 CDN 域名)
    imagePathFormat: "/Uploads/image/{yyyy}{mm}{dd}/{time}{rand:6}",

    // 檔案上傳
    fileActionName: "uploadfile",
    fileFieldName: "upfile",
    fileMaxSize: 51200000,        // 50MB
    fileAllowFiles: [".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".zip", ".rar"],
    filePathFormat: "/Uploads/file/{yyyy}{mm}{dd}/{time}{rand:6}",

    // 視頻上傳
    videoActionName: "uploadvideo",
    videoMaxSize: 102400000,      // 100MB
    videoAllowFiles: [".mp4", ".webm", ".ogg", ".mov", ".avi"],
    videoPathFormat: "/Uploads/video/{yyyy}{mm}{dd}/{time}{rand:6}",

    // 涂鴉、線上圖片抓取等其他設定...
    catcherActionName: "catchimage",
    catcherMaxSize: 2048000,
    catcherAllowFiles: [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
    catcherPathFormat: "/Uploads/image/{yyyy}{mm}{dd}/{time}{rand:6}",

    // 列出圖片/檔案(用於插入圖片對話框)
    imageManagerActionName: "listimage",
    imageManagerListPath: "/Uploads/image/",
    fileManagerActionName: "listfile",
    fileManagerListPath: "/Uploads/file/"
};

4. 核心上傳處理:Uploader.ashx / Uploader.cs

Uploader.ashx (入口)


<%@ WebHandler Language="C#" Class="Uploader" CodeBehind="Uploader.cs" %>

Uploader.cs 關鍵邏輯(節錄)


public class Uploader : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        // 1. 讀取 action 參數決定處理類型
        string action = context.Request["action"];
        
        // 2. 依 action 分派:uploadimage, uploadfile, uploadvideo, listimage, catchimage...
        switch (action)
        {
            case "uploadimage":
                UploadImage(context); break;
            case "uploadfile":
                UploadFile(context); break;
            // ...
        }
    }

    private void UploadImage(HttpContext context)
    {
        var file = context.Request.Files["upfile"]; // 對應 imageFieldName
        if (file == null || file.ContentLength == 0)
        {
            WriteResult(context, new { state = "ERROR", message = "無檔案" });
            return;
        }

        // 3. 驗證副檔名、大小
        string ext = Path.GetExtension(file.FileName).ToLower();
        if (!Config.ImageAllowFiles.Contains(ext))
        {
            WriteResult(context, new { state = "ERROR", message = "不允許的檔案類型" });
            return;
        }

        // 4. 產生儲存路徑(依 imagePathFormat 解析變數)
        string savePath = PathFormatter.Format(Config.ImagePathFormat, ext);
        string fullPath = context.Server.MapPath(savePath);
        Directory.CreateDirectory(Path.GetDirectoryName(fullPath));

        // 5. 儲存
        file.SaveAs(fullPath);

        // 6. 回傳 JSON (UEditor 要求格式)
        WriteResult(context, new 
        { 
            state = "SUCCESS", 
            url = savePath,           // 相對網站根目錄
            title = Path.GetFileName(file.FileName),
            original = Path.GetFileName(file.FileName)
        });
    }

    private void WriteResult(HttpContext context, object result)
    {
        context.Response.ContentType = "application/json";
        // 解決 IE9 以下下載 JSON 問題
        string callback = context.Request["callback"];
        string json = Newtonsoft.Json.JsonConvert.SerializeObject(result);
        if (!string.IsNullOrEmpty(callback))
            json = $"{callback}({json})";
        context.Response.Write(json);
    }
}

5. Web.config 關鍵設定


<configuration>
  <system.web>
    <!-- 允許大檔上傳 (預設 4MB) -->
    <httpRuntime maxRequestLength="102400" requestValidationMode="2.0" /> <!-- 100MB -->
    <pages validateRequest="false" /> <!-- 允許 HTML 內容提交 -->
  </system.web>
  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="104857600" /> <!-- 100MB (bytes) -->
      </requestFiltering>
    </security>
    <handlers>
      <add name="UEditorHandler" path="Ueditor/net/*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" />
    </handlers>
  </system.webServer>
</configuration>

6. 後端取得與儲存內容

WebForms


protected void btnSubmit_Click(object sender, EventArgs e)
{
    string htmlContent = txtContent.Value; // HtmlTextArea 控制項
    // 或 Request.Form["txtContent"]
    
    // 防 XSS:建議使用 HtmlSanitizer 過濾
    var sanitizer = new HtmlSanitizer();
    string safeHtml = sanitizer.Sanitize(htmlContent);
    
    // 儲存至資料庫
    ArticleService.Save(new Article { Content = safeHtml });
}

MVC Controller


[HttpPost]
[ValidateInput(false)] // 允許 HTML 提交,配合 [AllowHtml] 屬性更精確
public ActionResult Create(ArticleViewModel model)
{
    if (!ModelState.IsValid) return View(model);
    
    var sanitizer = new HtmlSanitizer();
    model.Content = sanitizer.Sanitize(model.Content);
    
    _articleService.Create(model);
    return RedirectToAction("Index");
}

public class ArticleViewModel
{
    [AllowHtml] // 僅此屬性允許 HTML
    public string Content { get; set; }
    // ...
}

7. 常見問題與解決

問題 原因 解決方案
上傳後圖片顯示 404 imagePathFormat 路徑與實際虛擬目錄不符 確認 imageUrlPrefix + imagePathFormat 組合為正確 URL,瀏覽器開發者工具 Network 面板檢查請求 URL
IE9/10 上傳回應被下載而非解析 回應 Content-Type 為 application/json,IE 誤判 Uploader.cs 中檢查 callback 參數輸出 JSONP,或設定 Response.ContentType = "text/html"
大檔上傳失敗 (404/500) maxRequestLength / maxAllowedContentLength 太小 調大 Web.config 兩處設定,並確認 IIS 應用程式集區限制
提交內容被截斷/編碼錯誤 validateRequest="true" 阻擋 HTML 頁面/控制器加 ValidateInput(false) 或 [AllowHtml],全域關閉風險較高
圖片上傳後編輯器不顯示 回傳 JSON 格式不符 UEditor 規範 必須包含 state: "SUCCESS", url, title, original 欄位
無法列出已上傳圖片 imageManagerListPath 指向錯誤目錄 確認虛擬路徑對應實體目錄,且 IIS 有讀取權限

8. 安全性加強建議

  1. 檔案類型驗證:僅檢查副檔名不足,需驗證 Content-Type、檔案簽名。
  2. 儲存路徑隔離:上傳目錄設為非執行權限(IIS Handler Mappings 移除 .aspx/.ashx/.php 等腳本映射)。
  3. 檔名隨機化:{time}{rand:6} 避免覆蓋與猜測。
  4. XSS 過濾:後端儲存前、前端顯示時雙重使用 HtmlSanitizer。
  5. 權限控制:Uploader.ashx 檢查用戶登入/角色,未授權回 401/403。
  6. 限流:單位時間上傳次數/大小限制。

9. 遷移至 ASP.NET Core 的替代方案

UEditor .NET 版維護較少,新專案建議考慮:

  • CKEditor 5:現代架構、TypeScript、完善生態、官方支援 ASP.NET Core。
  • TinyMCE:成熟商業支援、雲端圖片代理。
  • Quill / TipTap:輕量、可擴充、Vue/React 整合佳。
  • 自建上傳 API:前端編輯器只負責編輯,上傳走獨立 POST /api/upload,後端回傳 {url: "..."},解耦最徹底。

總結

  • UEditor .NET 整合核心:editor_config.js 設定 serverUrl、imagePathFormat、Web.config 放大上傳限制、Uploader.ashx 實作上傳邏輯並回傳標準 JSON。
  • 前端用 textarea + UE.getEditor('id'),後端用 Request.Form["id"] 取值。
  • 務必做 XSS 過濾、檔案驗證、目錄權限隔離。
  • 長期專案建議評估遷移至 CKEditor 5 或自建上傳 API 架構。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved