ASP.NET + CKEditor + CKFinder 整合教學

其實CKSource Docs網站上的文件寫的很清楚,但怕忘記,所以做個記錄。

  • CKEditor:3.3.2 (備份下載點)
    授權分兩種,商業用途要付費。
    CKEditor主要用途在「編輯」文件上,讓你可以更快速、更靈活的來進行編輯工作。
  • CKFinder:2.0 (備份下載點)
    目前提供的為「測試版」,在使用時會不斷顯示「這是Demo版本…」的訊息,不過功能不受影響,可以完整使用。

    CKFinder主要用途在「檔案管理」,你可以透過CKFinder直接上傳檔案到伺服器上,然後進行管理,而且CKFinder可以與CKEditor進行整合,也就是在CKEditor就可以進行上傳檔案及其他CKFinder的功能。

    目前CKFinder有分多個應用版本,因為我們以ASP.NET為主,所以請下載for asp.net的程式檔。
目前CKEditor及CKFinder的版本更新速度不算慢,如果你是用不同版本在實作,還是請參考原廠的說明為主。

以下分三個部份
  1. ASP.NET + CKEditor實作
  2. ASP.NET + CKFinder實作
  3. 整合CKEditor與CKFinder

ASP.NET + CKEditor教學實作

如果你還在使用舊版本FCKeditor,最好更新上來使用新版的CKEditor,因為FCKeditor本身設計及設定上有漏洞,例如x坤的這條新聞,所以良心建議,當你使用此類的Open Source時,要時時注意更新訊息,訂個RSS也好,當有更新時看一下是為什麼更新,如果是因為安全性問題而做的更新,那最好順便更新一下,等到出事就來不及。

  1. 下載CKEditor原始檔,我下載的是3.3.2版,解壓縮,然後將ckeditor目錄複製或拉進Vistual Studio專案根目錄裡;(裡面有兩個目錄_samples、_source,學習可以留著看,正式上線就不要留了)
  2. 在*.aspx裡引用ckeditor.js指令碼,例如:
    <script src="ckeditor/ckeditor.js" type="text/javascript" >  </script>
    
  3. 放入一個Textbox控制項,有幾個重點:
    ID:ckdata
    TextMode:MultiLine
    Rows:10
    Columns:80
    ClientIDMode:Static (.NET Framework 4)
  4. 在控制項下方撰寫Javascript指令碼
    <script type="text/javascript">
            CKEDITOR.replace('<%= ckdata.ClientID %>', {skin : 'kama'}); 
    </script>
    

    這裡主要是把Textbox的ID帶給CKEditor來使用,CKEditor才知道要把那一個Textbox變成「編輯區」。而最後{...}裡是主要細項設定的地方,可以用來改變CKEditor,例如skin是用來改變外觀,其他細部設定,請參考CKEditor 3.x - Developers Guide中Configuration一節。

    另外,請務必把此段Javascript放到Textbox控制項的下方,如果放在head裡,會沒有效果。

IntelliSense
在撰寫Javascript的過程,IntelliSense會自己提示相關方法等,就甘心啦

最後完成的程式碼為:

<div>
        <asp:TextBox ID="ckdata" runat="server" TextMode="MultiLine" Rows="10" 
            Columns="80" ClientIDMode="Static"></asp:TextBox>
            <script type="text/javascript" >
                CKEDITOR.replace('<%= ckdata.ClientID %>', {skin: 'kama'});
            </script>
    </div>

然後執行網頁:

CKEditor介面

接下來,我們在畫面上放一個Button控制項及Lable控制項,我們要把Textbox的值取出來。
<div>
        <asp:TextBox ID="ckdata" runat="server" TextMode="MultiLine" Rows="10" 
            Columns="80" ClientIDMode="Static"></asp:TextBox>
            <script type="text/javascript" >
                CKEDITOR.replace('<%= ckdata.ClientID %>', {skin: 'kama'});
            </script>

        <asp:Button ID="SendData" runat="server" Text="Button" />
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </div>

  '後置程式碼
    Protected Sub SendData_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SendData.Click
        Me.Label1.Text = Me.ckdata.Text
    End Sub

執行後,隨便輸入一些文字,然後送出!!!

錯誤訊息
ASP.NET本身不許包含有html標籤的資料內容,必須取消驗證,在錯誤訊息裡有提供解決辦法。在.NET Framework 4.0裡需要兩個步驟:
  1. 在開頭宣告裡加上屬性validateRequest="false";
  2. 在web.config裡新增httpRuntime標籤

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="DemoCKEditor.aspx.vb" Inherits="DemoCKEditor" ValidateRequest="false" %>

'web.confg
    <system.web>
        <compilation debug="false" strict="false" explicit="true" targetFramework="4.0" />
        <httpRuntime requestValidationMode ="2.0"/>
    </system.web>

在.NET Framwork 3.5 SP1之前,只需要步驟1即可。

再為Button加上一些保護:

  '後置程式碼
    Protected Sub SendData_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SendData.Click
        Me.Label1.Text = HttpUtility.HtmlEncode(Me.ckdata.Text)
    End Sub

非常建議所有只要是「人工輸入」的內容都使用HttpUtility.HtmlEncode方法加以保護。

取得Textbox控制項的值
基本上到這裡就已經差不多了,其他的細節就都必須由第二個參數{…}去調整。最後來看一張圖:

影像屬性
在最後面CKEditor與CKFinder整合裡你可以看到Link、Image、Flash就可以直接進行檔案上傳及管理動作,目前還沒有。

ASP.NET + CKFinder教學實作

  1. 下載CKFinder原始檔,我下載的是2.0版(28.05.2010),解壓縮,然後將ckfinder目錄複製或拉進Vistual Studio專案ckeditor目錄之下;(裡面有兩個目錄_samples、_source,學習可以留著看,正式上線就不要留了)下載CKFinder原始檔。
  2. 在ASP.NET專案之下新增一個目錄,用來上載之用。我們在根目鍵之下新增一個「uploads」目錄。CKFinder預設使用"/ckfinder/userfiles/"目錄。
  3. 檢查上載目錄權限,必須有寫入的權限。給IUSR_<ServerName>角色寫入的權限。
  4. 編輯...檔案。 

加入CKFinder目錄之下

然後在Bin目錄之下「加入參考」,將「CKFinder\bin\CKFinder.dll」加入。

加入CKFinder.dll參考

編輯config.ascx檔:

認證:有通過認證才能使用。
public override bool CheckAuthentication()
 {
  // WARNING : DO NOT simply return "true". By doing so, you are allowing
  // "anyone" to upload and list the files in your server. You must implement
  // some kind of session validation here. Even something very simple as...
  //
  //  return ( Session[ "IsAuthorized" ] != null && (bool)Session[ "IsAuthorized" ] == true );
  //
  // ... where Session[ "IsAuthorized" ] is set to "true" as soon as the
  // user logs on your system.

  //return false;
        return true;
 }
作者苦口婆心請大家不要設為「true;」,請大家注意,測試時還沒關係,正式上線一定一定要設為false

主要設定:
public override void SetConfig()
 {
  // Paste your license name and key here. If left blank, CKFinder will
  // be fully functional, in Demo Mode.
  LicenseName = "";
  LicenseKey = "";

  // The base URL used to reach files in CKFinder through the browser.
  //BaseUrl = "/ckfinder/userfiles/";
            BaseUrl = "http://localhost:49559/DemoEditor/uploads/";

  // The phisical directory in the server where the file will end up. If
  // blank, CKFinder attempts to resolve BaseUrl.
            BaseDir = "F:/WebDevelop/Study/StudyTest/DemoEditor/uploads/";

  // Optional: enable extra plugins (remember to copy .dll files first).
  Plugins = new string[] {
   // "CKFinder.Plugins.FileEditor, CKFinder_FileEditor",
   // "CKFinder.Plugins.ImageResize, CKFinder_ImageResize"
  };
  // Settings for extra plugins.
  PluginSettings = new Hashtable();
  PluginSettings.Add("ImageResize_smallThumb", "90x90" );
  PluginSettings.Add("ImageResize_mediumThumb", "120x120" );
  PluginSettings.Add("ImageResize_largeThumb", "180x180" );

  // Thumbnail settings.
  // "Url" is used to reach the thumbnails with the browser, while "Dir"
  // points to the physical location of the thumbnail files in the server.
  Thumbnails.Url = BaseUrl + "_thumbs/";
  if ( BaseDir != "" ) {
   Thumbnails.Dir = BaseDir + "_thumbs/";
  }
  Thumbnails.Enabled = true;
  Thumbnails.DirectAccess = false;
  Thumbnails.MaxWidth = 100;
  Thumbnails.MaxHeight = 100;
  Thumbnails.Quality = 80;

  // Set the maximum size of uploaded images. If an uploaded image is
  // larger, it gets scaled down proportionally. Set to 0 to disable this
  // feature.
  Images.MaxWidth = 1600;
  Images.MaxHeight = 1200;
  Images.Quality = 80;

  // Indicates that the file size (MaxSize) for images must be checked only
  // after scaling them. Otherwise, it is checked right after uploading.
  CheckSizeAfterScaling = true;

  // Due to security issues with Apache modules, it is recommended to leave the
  // following setting enabled. It can be safely disabled on IIS.
  ForceSingleExtension = true;

  // For security, HTML is allowed in the first Kb of data for files having the
  // following extensions only.
  HtmlExtensions = new string[] { "html", "htm", "xml", "js" };

  // Folders to not display in CKFinder, no matter their location. No
  // paths are accepted, only the folder name.
  // The * and ? wildcards are accepted.
  HideFolders = new string[] { ".svn", "CVS" };

  // Files to not display in CKFinder, no matter their location. No
  // paths are accepted, only the file name, including extension.
  // The * and ? wildcards are accepted.
  HideFiles = new string[] { ".*" };

  // Perform additional checks for image files.
  SecureImageUploads = true;

  // The session variable name that CKFinder must use to retrieve the
  // "role" of the current user. The "role" is optional and can be used
  // in the "AccessControl" settings (bellow in this file).
  RoleSessionVar = "CKFinder_UserRole";

  // ACL (Access Control) settings. Used to restrict access or features
  // to specific folders.
  // Several "AccessControl.Add()" calls can be made, which return a
  // single ACL setting object to be configured. All properties settings
  // are optional in that object.
  // Subfolders inherit their default settings from their parents' definitions.
  //
  // - The "Role" property accepts the special "*" value, which means
  //   "everybody".
  // - The "ResourceType" attribute accepts the special value "*", which
  //   means "all resource types".
  AccessControl acl = AccessControl.Add();
  acl.Role = "*";
  acl.ResourceType = "*";
  acl.Folder = "/";

  acl.FolderView = true;
  acl.FolderCreate = true;
  acl.FolderRename = true;
  acl.FolderDelete = true;

  acl.FileView = true;
  acl.FileUpload = true;
  acl.FileRename = true;
  acl.FileDelete = true;

  // Resource Type settings.
  // A resource type is nothing more than a way to group files under
  // different paths, each one having different configuration settings.
  // Each resource type name must be unique.
  // When loading CKFinder, the "type" querystring parameter can be used
  // to display a specific type only. If "type" is omitted in the URL,
  // the "DefaultResourceTypes" settings is used (may contain the
  // resource type names separated by a comma). If left empty, all types
  // are loaded.

  DefaultResourceTypes = "";

  ResourceType type;

  type = ResourceType.Add( "Files" );
  type.Url = BaseUrl + "files/";
  type.Dir = BaseDir == "" ? "" : BaseDir + "files/";
  type.MaxSize = 0;
  type.AllowedExtensions = new string[] { "7z", "aiff", "asf", "avi", "bmp", "csv", "doc", "docx", "fla", "flv", "gif", "gz", "gzip", "jpeg", "jpg", "mid", "mov", "mp3", "mp4", "mpc", "mpeg", "mpg", "ods", "odt", "pdf", "png", "ppt", "pptx", "pxd", "qt", "ram", "rar", "rm", "rmi", "rmvb", "rtf", "sdc", "sitd", "swf", "sxc", "sxw", "tar", "tgz", "tif", "tiff", "txt", "vsd", "wav", "wma", "wmv", "xls", "xlsx", "zip" };
  type.DeniedExtensions = new string[] { };

  type = ResourceType.Add( "Images" );
  type.Url = BaseUrl + "images/";
  type.Dir = BaseDir == "" ? "" : BaseDir + "images/";
  type.MaxSize = 0;
  type.AllowedExtensions = new string[] { "bmp", "gif", "jpeg", "jpg", "png" };
  type.DeniedExtensions = new string[] { };

  type = ResourceType.Add( "Flash" );
  type.Url = BaseUrl + "flash/";
  type.Dir = BaseDir == "" ? "" : BaseDir + "flash/";
  type.MaxSize = 0;
  type.AllowedExtensions = new string[] { "swf", "flv" };
  type.DeniedExtensions = new string[] { };
 }

重要的有:
LicenseName = "";
LicenseKey = "";
這兩項是正式購買後可以取消提示訊息。

BaseUrl = "/ckfinder/userfiles/";
BaseDir = ""

我一開始使用預設值,但一直出現一個「110 : 不明錯誤」,後來查看文件後,最好的方式是:
BaseUrl使用完整網域路徑;
BaseDir使用完整實體路徑;

type.*
用來新增上載目錄、目錄路徑、類型、大小限制、副檔名限制…如果你需要有新的分類目錄,就從這裡下手,複製一份type.*的Code,修改為你需要的設定即可。預設有Files、Images、Flash三項,當你上載第一個檔案後,會在你設定上載目錄新增對應的子目錄。

執行測試檔「ckeditor\ckfinder\_samples\aspx\standalone.aspx」
CKFinder
按上傳檔案可以上傳檔案,在上傳好的檔案按左鍵,會出現管理選單。

那我要在一般*.aspx裡使用CKFinder呢?也很簡單:
  1. 先註冊CKFinder
  2. 使用CKFinder控制項

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" nherits="_Default" %>
<%@ Register Assembly="CKFinder" Namespace="CKFinder" TagPrefix="CKFinder" %>
' ... 略 ...
    <div>
        <CKFinder:FileBrowser ID="FileBrowser1" BasePath="ckeditor/ckfinder/" Width="800" runat="server">
        </CKFinder:FileBrowser>
    </div>

注意:
在使用CKFinder時,所特別注意「路徑」問題,請搞清楚「絕對路徑」與「相對路徑」,絕大部出錯都是路徑有問題,例如在不同資料夾裡</CKFinder:FileBrowser ...>裡的BasePath路徑就會不一樣。

整合CKEditor與CKFinder教學實作


要整合CKEditor與CKFinder也很簡單,原始的JavaScript裡增加以下參數即可。

啟用CKFinder
CKEDITOR.replace( '<%= ckdata.ClientID %>',
 {
 //注意路徑是否正確 
  //如果你的*.aspx在根目錄,那路徑應該是「ckeditor/ckfinder/...」
  filebrowserBrowseUrl : '/ckfinder/ckfinder.html',
  filebrowserImageBrowseUrl : '/ckfinder/ckfinder.html?type=Images',
  filebrowserFlashBrowseUrl : '/ckfinder/ckfinder.html?type=Flash',
  filebrowserUploadUrl : '/ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Files',
  filebrowserImageUploadUrl : '/ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Images',
  filebrowserFlashUploadUrl : '/ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Flash'
 } 
 );

CKEditor中的CKFinder功能
不管是CKEditor或CKFinder都提供很好的解決方案,讓我們可以快速產生功能強大編輯區、上下載管理功能。不過其中還有許多細節,建議細讀原廠的文件,把不必要的功能關閉,例如限制副檔名…來減少不必要的風險。

參考:
CKSource Docs

下載CKEditor與CKFinder範例檔

10 則留言:

  1. CKFinder 並不是測試版,也不是免費。
    http://ckfinder.com/purchase

    回覆刪除
  2. Dear Ammon
    感謝你的提醒。

    可能用詞上理解不同,我知道這是要付費的,但它提供的功能完整,只差會一直提示這是Demo版本…,所以我定義為「測試版」,即只能使用在測試環境,如果要正式上線使用,還是必須採購其授權,授權部份我在最後一段也有介紹。

    回覆刪除
  3. 感謝您的分享~
    最近也在嘗試這個東西,
    感謝~

    回覆刪除
  4. 2011/11月會有幾篇 ASP.NET MVC版本,有興趣再回來看。

    回覆刪除
  5. 在整合之後
    有沒有辦法修改程式讓code不要讓使用者直接上傳
    而是從Browser之後,選擇上傳的目錄再上傳

    回覆刪除
  6. http://blog.kkbruce.net/2011/11/aspnet-mvc-html-3-ckeditor-ckfinder.html#.Tyt1-Fz9PD8

    這是ASP.NET MVC版本的文章。

    回覆刪除
  7. 請教大家
    有遇過下列的情況嗎:執行CKFinder,會出現下列的訊息:因為安全因素,檔案瀏覽器已被停用!請聯絡您的系統管理者並檢查CKFinder的設定檔config.php!
    https://drive.google.com/file/d/0BxriXuT0xeaFLVZmUjNxcmNfaEU/view?usp=sharing

    我的uploads資料夾權限設定如網址:https://drive.google.com/file/d/0BxriXuT0xeaFN1ZPX29TcGRYTFU/view?usp=sharing
    感謝

    回覆刪除
    回覆
    1. 在本機測試時,設定為true,就不會出現錯誤了
      public override bool CheckAuthentication()
      {
      // WARNING : DO NOT simply return "true". By doing so, you are allowing
      // "anyone" to upload and list the files in your server. You must implement
      // some kind of session validation here. Even something very simple as...
      //
      // return ( Session[ "IsAuthorized" ] != null && (bool)Session[ "IsAuthorized" ] == true );
      //
      // ... where Session[ "IsAuthorized" ] is set to "true" as soon as the
      // user logs on your system.

      //return false;
      return true;
      }

      刪除
  8. 請教, 是否有這範例檔可參考呢? 因為照著做無法成功, 謝謝

    回覆刪除

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。