Viết thêm plugin upload file cho CKEditor

Viết thêm plugin upload file cho CKEditor

Trong các CMS thì vấn đề soạn thảo nội dung văn bản là bắt buộc phải có.
Có 1 số editor mã nguồn mở như FCKEditor, tinyMCE, CKEditor.

Nhưng khi bạn tích hợp vào thì các tính năng Upload hình ảnh để chèn thêm từ máy mình đều phải mua bằng license.
FCKEditor thì có full chức năng upload ảnh từ máy lên nhưng mình test thử trên Chrome thì lỗi.
PHP thì có 1 số plugin mã mở có chức năng này nhưng còn .Net thì không thấy.
Vì thế tại sao không viết thêm 1 plugin upload file đơn giản có khả năng chèn ảnh từ file mình lên. Sau đây mình xin trình bày cách viết 1 plugin upload file .

- Ví dụ dưới đây mình sẽ dùng ngôn ngữ là .Net code trên mô hình MVC3. Upload file thì có các cách như dùng formdata của HTML5, post ngầm nội dung file ra iframe, dùng flash để upload. Mình xin giới thiệu cách dùng ajax và formdata của HTML5 để upload file lên server vì các trình duyệt hay dùng như firefox, CHrome đều đã hỗ trợ HTML5.

Đầu tiên các bạn mở VS2010 lên chọn file->new->project. Chọn ASP.NET MVC3 Web application

Tiếp theo ta add thêm 1 controller đặt tên là UploadController đi

Add thêm 1 view từ controller Upload. Ấn chuôt phải vào ActionResult Index chọn add View đặt tên là Index.

Vào trang chủ ckeditor download plugin. CHọn bản 4.0.1 .

Tiếp theo đó giải nén ra và được 1 thư mục ckeditor. Copy luôn vào project rồi chọn Show all file. Sau đó include thêm thư mục ckeditor vào dự án.

Để chạy project vào luôn vào trang upload vừa tạo ra mở file Global.asax ra. Đổi router view thành controller = Upload

 new { controller = "Upload", action = "Index", id = UrlParameter.Optional } // Parameter defaults

- Mở file View\Upload\Index.cshtml ra để include thư viện jQuery và CKEditor. Chú ý tạo thêm 1 textarea id là description để CKEditor load vào đó.

@{
    Layout = null;
}
<!--jQuery-->
<script src="@Url.Content("~/Scripts/jquery-1.5.1.js")" type="text/javascript"></script>
<!--CKEDITOR-->
<script src="@Url.Content("~/ckeditor/ckeditor.js")" type="text/javascript"></script>
<script type="text/javascript">// <![CDATA[
    $(document).ready(function () {
        CKEDITOR.replace('Description', {
            extraPlugins: 'uploadimage'
        });
    });
// ]]></script>
<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        <textarea id="Description" style="width:100%;height:1000px;"></textarea>
    </div>
</body>
</html>

Để viết thêm plugin cho CKEditor ta tạo thêm 1 folder lấy tên là uploadimage trong thư mục ckeditor/plugins.

Trong thư mục uploadimage vừa tạo ra có cấu trúc như sau

images/icon.png -> chứa ảnh của nút upload. Kích cỡ nên để 16×16 pixel

plugin.js                 -> Chứa toàn bộ nội dung xử lý của plugin này.

Nội dung file plugin.js

/**
* Basic sample plugin inserting abbreviation elements into CKEditor editing area.
*/
// Written by QuyetNV(19/01/2013)
// Plugin upload image using Jquery,Ajax,Html5
// Register the plugin with the editor.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.plugins.html

CKEDITOR.plugins.add('uploadimage',
{
    init: function (editor) {
        editor.addCommand('abbrDialog', new CKEDITOR.dialogCommand('abbrDialog'));
        editor.ui.addButton('Abbr',
		{
		    label: 'Chèn ảnh lên',
		    command: 'abbrDialog',
		    icon: this.path + 'images/icon.png'
		});

        CKEDITOR.dialog.add('abbrDialog', function (editor) {
            return {
                title: 'Upload ảnh',
                minWidth: 400,
                minHeight: 200,
                contents:
				[
					{
					    id: 'tab1',
					    label: 'Basic Settings',
                        elements:
						[
                            {
                                type: 'html',
html: "</pre>
<div><form id="form1" action="Upload.aspx" method="post" enctype="multipart/form-data">
<div class="row"><label for="fileToUpload">Select a File to Upload</label>
<input id="fileToUpload" type="file" name="fileToUpload" onchange="fileSelected();" /></div>
<div id="fileName"></div>
<div id="fileSize"></div>
<div id="fileType"></div>
<div class="row"></div>
<div id="progressNumber"></div>
</form></div>
<pre>
"
                            }
						]
					}
				],
                onOk: function () {
                    var ketqua = JSON.parse( uploadFile() );
                    editor.insertHtml("</pre>
<img src="&quot;+ ketqua.url+ &quot;" alt="" />
<pre>" );
                }
            };
        });
    }
});

/**************************************Upload file **********************************/
function fileSelected() {
var file = document.getElementById('fileToUpload').files[0];
if (file) {
    var fileSize = 0;
    if (file.size > 1024 * 1024)
    fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
    else
    fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';

    document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
    document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
    document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
}
}

function uploadFile() {
    var fd = new FormData();
    fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
    var xhr = new XMLHttpRequest();
    xhr.upload.addEventListener("progress", uploadProgress, false);
    xhr.addEventListener("load", uploadComplete, false);
    xhr.addEventListener("error", uploadFailed, false);
    xhr.addEventListener("abort", uploadCanceled, false);
    xhr.open("POST", "/Upload/UploadUsingCK/" , false);
    xhr.send(fd);
    return(xhr.responseText);
}

function uploadProgress(evt) {
    if (evt.lengthComputable) {
        var percentComplete = Math.round(evt.loaded * 100 / evt.total);
        document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
    }
    else {
        document.getElementById('progressNumber').innerHTML = 'unable to compute';
    }
}

function uploadComplete(evt) {
    return evt.target.responseText;
}

function uploadFailed(evt) {
    alert("There was an error attempting to upload the file.");
}

function uploadCanceled(evt) {
    alert("The upload has been canceled by the user or the browser dropped the connection.");
}

Đoạn script trên add thêm 1 button imageupload vào.Khi click vào mở ra 1 dialog. Có nút chọn file . Sau khi chọn ấn ok dùng ajax và viết 1 thêm action UploadUsingCK trong controller Upload xử lý lưu file lên server. Nội dung action UploadUsingCK

const string UploadPath = "/uploads/";
[HttpPost]
        public JsonResult UploadUsingCK(HttpPostedFileBase fileToUpload)
        {
            string resultIconUrl = "";
            // Check xem phải có file được submit
            if (fileToUpload != null && fileToUpload.ContentLength > 0)
            {
                // Biến lưu tên file
                var fileName = Path.GetFileName(fileToUpload.FileName);
                if (System.IO.File.Exists(Server.MapPath("~" + UploadPath + fileName)))
                {
                    // cắt chuỗi bởi dấu '.' -> lấy phần mở rộng của tập tin, ví dụ .jpg, .doc, ...
                    string[] fileParts = fileName.Split(new char[] { '.' });
                    fileName = fileParts[0] + "2" + "." + fileParts[1];
                }
                //Lấy địa chỉ của ảnh IconUrl
                resultIconUrl = UploadPath + fileName;
                // Lưu file vào ~/App_Data/uploads folder
                var path = Path.Combine(Server.MapPath("~" + UploadPath), fileName);
                fileToUpload.SaveAs(path);
            }
            return Json(new { url = resultIconUrl }, JsonRequestBehavior.AllowGet);
        }


Toàn bộ mã nguồn có thể down ở link sau
MVCDemoPluginCKEditor

Khi trích dẫn bài viết từ tek.eten.vn, xin vui lòng ghi rõ nguồn. Chúng tôi sẽ rất cảm ơn bạn!