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指令碼,例如:
    1<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指令碼
    1<script type="text/javascript">
    2        CKEDITOR.replace('<%= ckdata.ClientID %>', {skin : 'kama'});
    3</script>

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

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

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

最後完成的程式碼為:

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

然後執行網頁:

CKEditor介面

接下來,我們在畫面上放一個Button控制項及Lable控制項,我們要把Textbox的值取出來。
01<div>
02        <asp:TextBox ID="ckdata" runat="server" TextMode="MultiLine" Rows="10"
03            Columns="80" ClientIDMode="Static"></asp:TextBox>
04            <script type="text/javascript" >
05                CKEDITOR.replace('<%= ckdata.ClientID %>', {skin: 'kama'});
06            </script>
07 
08        <asp:Button ID="SendData" runat="server" Text="Button" />
09        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
10    </div>
11 
12  '後置程式碼
13    Protected Sub SendData_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SendData.Click
14        Me.Label1.Text = Me.ckdata.Text
15    End Sub

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

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

1<%@ Page Language="VB" AutoEventWireup="false" CodeFile="DemoCKEditor.aspx.vb" Inherits="DemoCKEditor" ValidateRequest="false" %>
2 
3'web.confg
4    <system.web>
5        <compilation debug="false" strict="false" explicit="true" targetFramework="4.0" />
6        <httpRuntime requestValidationMode ="2.0"/>
7    </system.web>

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

再為Button加上一些保護:

1'後置程式碼
2  Protected Sub SendData_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SendData.Click
3      Me.Label1.Text = HttpUtility.HtmlEncode(Me.ckdata.Text)
4  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檔:

認證:有通過認證才能使用。
01public override bool CheckAuthentication()
02 {
03  // WARNING : DO NOT simply return "true". By doing so, you are allowing
04  // "anyone" to upload and list the files in your server. You must implement
05  // some kind of session validation here. Even something very simple as...
06  //
07  //  return ( Session[ "IsAuthorized" ] != null && (bool)Session[ "IsAuthorized" ] == true );
08  //
09  // ... where Session[ "IsAuthorized" ] is set to "true" as soon as the
10  // user logs on your system.
11 
12  //return false;
13        return true;
14 }
作者苦口婆心請大家不要設為「true;」,請大家注意,測試時還沒關係,正式上線一定一定要設為false

主要設定:
001public override void SetConfig()
002 {
003  // Paste your license name and key here. If left blank, CKFinder will
004  // be fully functional, in Demo Mode.
005  LicenseName = "";
006  LicenseKey = "";
007 
008  // The base URL used to reach files in CKFinder through the browser.
009  //BaseUrl = "/ckfinder/userfiles/";
010            BaseUrl = "http://localhost:49559/DemoEditor/uploads/";
011 
012  // The phisical directory in the server where the file will end up. If
013  // blank, CKFinder attempts to resolve BaseUrl.
014            BaseDir = "F:/WebDevelop/Study/StudyTest/DemoEditor/uploads/";
015 
016  // Optional: enable extra plugins (remember to copy .dll files first).
017  Plugins = new string[] {
018   // "CKFinder.Plugins.FileEditor, CKFinder_FileEditor",
019   // "CKFinder.Plugins.ImageResize, CKFinder_ImageResize"
020  };
021  // Settings for extra plugins.
022  PluginSettings = new Hashtable();
023  PluginSettings.Add("ImageResize_smallThumb", "90x90" );
024  PluginSettings.Add("ImageResize_mediumThumb", "120x120" );
025  PluginSettings.Add("ImageResize_largeThumb", "180x180" );
026 
027  // Thumbnail settings.
028  // "Url" is used to reach the thumbnails with the browser, while "Dir"
029  // points to the physical location of the thumbnail files in the server.
030  Thumbnails.Url = BaseUrl + "_thumbs/";
031  if ( BaseDir != "" ) {
032   Thumbnails.Dir = BaseDir + "_thumbs/";
033  }
034  Thumbnails.Enabled = true;
035  Thumbnails.DirectAccess = false;
036  Thumbnails.MaxWidth = 100;
037  Thumbnails.MaxHeight = 100;
038  Thumbnails.Quality = 80;
039 
040  // Set the maximum size of uploaded images. If an uploaded image is
041  // larger, it gets scaled down proportionally. Set to 0 to disable this
042  // feature.
043  Images.MaxWidth = 1600;
044  Images.MaxHeight = 1200;
045  Images.Quality = 80;
046 
047  // Indicates that the file size (MaxSize) for images must be checked only
048  // after scaling them. Otherwise, it is checked right after uploading.
049  CheckSizeAfterScaling = true;
050 
051  // Due to security issues with Apache modules, it is recommended to leave the
052  // following setting enabled. It can be safely disabled on IIS.
053  ForceSingleExtension = true;
054 
055  // For security, HTML is allowed in the first Kb of data for files having the
056  // following extensions only.
057  HtmlExtensions = new string[] { "html", "htm", "xml", "js" };
058 
059  // Folders to not display in CKFinder, no matter their location. No
060  // paths are accepted, only the folder name.
061  // The * and ? wildcards are accepted.
062  HideFolders = new string[] { ".svn", "CVS" };
063 
064  // Files to not display in CKFinder, no matter their location. No
065  // paths are accepted, only the file name, including extension.
066  // The * and ? wildcards are accepted.
067  HideFiles = new string[] { ".*" };
068 
069  // Perform additional checks for image files.
070  SecureImageUploads = true;
071 
072  // The session variable name that CKFinder must use to retrieve the
073  // "role" of the current user. The "role" is optional and can be used
074  // in the "AccessControl" settings (bellow in this file).
075  RoleSessionVar = "CKFinder_UserRole";
076 
077  // ACL (Access Control) settings. Used to restrict access or features
078  // to specific folders.
079  // Several "AccessControl.Add()" calls can be made, which return a
080  // single ACL setting object to be configured. All properties settings
081  // are optional in that object.
082  // Subfolders inherit their default settings from their parents' definitions.
083  //
084  // - The "Role" property accepts the special "*" value, which means
085  //   "everybody".
086  // - The "ResourceType" attribute accepts the special value "*", which
087  //   means "all resource types".
088  AccessControl acl = AccessControl.Add();
089  acl.Role = "*";
090  acl.ResourceType = "*";
091  acl.Folder = "/";
092 
093  acl.FolderView = true;
094  acl.FolderCreate = true;
095  acl.FolderRename = true;
096  acl.FolderDelete = true;
097 
098  acl.FileView = true;
099  acl.FileUpload = true;
100  acl.FileRename = true;
101  acl.FileDelete = true;
102 
103  // Resource Type settings.
104  // A resource type is nothing more than a way to group files under
105  // different paths, each one having different configuration settings.
106  // Each resource type name must be unique.
107  // When loading CKFinder, the "type" querystring parameter can be used
108  // to display a specific type only. If "type" is omitted in the URL,
109  // the "DefaultResourceTypes" settings is used (may contain the
110  // resource type names separated by a comma). If left empty, all types
111  // are loaded.
112 
113  DefaultResourceTypes = "";
114 
115  ResourceType type;
116 
117  type = ResourceType.Add( "Files" );
118  type.Url = BaseUrl + "files/";
119  type.Dir = BaseDir == "" ? "" : BaseDir + "files/";
120  type.MaxSize = 0;
121  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" };
122  type.DeniedExtensions = new string[] { };
123 
124  type = ResourceType.Add( "Images" );
125  type.Url = BaseUrl + "images/";
126  type.Dir = BaseDir == "" ? "" : BaseDir + "images/";
127  type.MaxSize = 0;
128  type.AllowedExtensions = new string[] { "bmp", "gif", "jpeg", "jpg", "png" };
129  type.DeniedExtensions = new string[] { };
130 
131  type = ResourceType.Add( "Flash" );
132  type.Url = BaseUrl + "flash/";
133  type.Dir = BaseDir == "" ? "" : BaseDir + "flash/";
134  type.MaxSize = 0;
135  type.AllowedExtensions = new string[] { "swf", "flv" };
136  type.DeniedExtensions = new string[] { };
137 }

重要的有:
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控制項

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

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

整合CKEditor與CKFinder教學實作


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

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

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. 請教, 是否有這範例檔可參考呢? 因為照著做無法成功, 謝謝

    回覆刪除

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