1

we have a textarea using CKEditor 4.4 on our admin website where users can edit content. They would like to be able to add images from their computer and have them uploaded automatically to the server for hosting.

I've seen a number of image upload scripts for CKEditor, but they all come with a PHP back-end. Does one exist for ASP.NET MVC 4?

I've seen this post and this one which show server-side controls for WebForms, but haven't been able to find an MVC version that we could drop in, or modify to our tastes.

Is my only option to use one of the existing PHP plugins and rewrite the endpoints as ASP.NET MVC?

Thanks.

Community
  • 1
  • 1
Peter
  • 1,674
  • 4
  • 27
  • 44
  • 1
    These aren't exactly MVC samples, but you can find a sample in vb.net and c# to handle uploads from CKEditor: https://github.com/AlfonsoML/CKEditorUploader Pick the code that you want and adjust it to your CMS. – AlfonsoML Oct 19 '15 at 21:24
  • Thanks @AlfonsoML, you should consider putting this as an answer! – Peter Oct 20 '15 at 07:18

4 Answers4

2

Based on Alfonso's WebForms code mentioned in the accepted answer, I ended up using a script similar to this in MVC:

using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class CKEditorController : Controller
    {
        const string basePath = @"D:\CKFinder\ckfinder\userfiles\";
        const string baseUrl = @"/ckfinder/userfiles/";

        const string scriptTag = "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction({0}, '{1}', '{2}')</script>";

        public ActionResult Index()
        {
            var funcNum = 0;
            int.TryParse(Request["CKEditorFuncNum"], out funcNum);

            if (Request.Files == null || Request.Files.Count < 1)
                return BuildReturnScript(funcNum, null, "No file has been sent");

            if (!System.IO.Directory.Exists(basePath))
                return BuildReturnScript(funcNum, null, "basePath folder doesn't exist");

            var receivedFile = Request.Files[0];

            var fileName = receivedFile.FileName;
            if (string.IsNullOrEmpty(fileName))
            {
                return BuildReturnScript(funcNum, null, "File name is empty");
            }

            var sFileName = System.IO.Path.GetFileName(fileName);

            var nameWithFullPath = System.IO.Path.Combine(basePath, sFileName);
            //Note: you may want to consider using your own naming convention for files, as this is vulnerable to overwrites
            //e.g. at the moment if two users uploaded a file called image1.jpg, one would clash with the other.
            //In the past, I've used Guid.NewGuid() combined with the file extension to ensure uniqueness.
            receivedFile.SaveAs(nameWithFullPath);

            var url = baseUrl + sFileName;

            return BuildReturnScript(funcNum, url, null);
        }

        private ContentResult BuildReturnScript(int functionNumber, string url, string errorMessage)
        {
            return Content(
                string.Format(scriptTag, functionNumber, HttpUtility.JavaScriptStringEncode(url ?? ""), HttpUtility.JavaScriptStringEncode(errorMessage ?? "")),
                "text/html"
                );
        }
    }
}
Peter
  • 1,674
  • 4
  • 27
  • 44
  • I get "incorrect server response" when using this code. Isn't ckeditor expecting the response to be Json ? – simon831 Dec 14 '15 at 17:30
  • @peter - I am getting - "Incorrect server response" with this code. Am i missing any configuration in ckeditor? – Krishnraj Rana Jan 10 '20 at 13:30
  • @KrishnrajRana I'm afraid it's been nearly five years since I have had to look at CKEditor, you should check their latest documentation for what responses they now expect. – Peter Jan 17 '20 at 10:34
1

The plugin sends the image asynchronously to the server. As long as you have an ASP.NET MVC/Web Api end point to accept the image and save it to the relavant place/update relevant tables, You should be good. Make sure you return data which your plugin is expecting.

for example, from the demo page you provided, the PHP server page is returning the following string on successful upload of the image

<script type="text/javascript">
    window.parent.CKEDITOR.tools.callFunction("92", "\/userfiles\/images\/myImgy.jpg", "");
</script>

In your Web api endpoint, You can use HttpContext.Current.Request.Files collection to look for the posted files.

Shyju
  • 214,206
  • 104
  • 411
  • 497
1

These aren't exactly MVC samples, but you can find a sample in VB.Net and C# to handle uploads from CKEditor: https://github.com/AlfonsoML/CKEditorUploader

Pick the code that you want and adjust it to your CMS.

AlfonsoML
  • 12,634
  • 2
  • 46
  • 53
1

Try this

Html and JavaScript

 <script src="~/Vendors/ckeditor/ckeditor.js"></script>
 <script src="~/Vendors/ckeditor/adapters/jquery.js"></script>
    <div class="jumbotron">
            <textarea name="editor1"></textarea>
            <script>
                CKEDITOR.replace('editor1', {
                    uiColor: '#9AB8F3',
                    filebrowserUploadUrl: '/CkEditorUpload/'
                });
            </script>

    </div>

Controller

using System;
using System.IO;
using System.Web;
using System.Web.Mvc;

namespace ImageUploadCkEditor.Controllers
{

        public class CkEditorUploadController : Controller
        {
        const string filesavepath = "~/Content/Uploads/Ckeditor";
        const string baseUrl = @"/Content/Uploads/Ckeditor/";

        const string scriptTag = "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction({0}, '{1}', '{2}')</script>";

            public ActionResult Index()
            {
                var funcNum = 0;
                int.TryParse(Request["CKEditorFuncNum"], out funcNum);

                if (Request.Files == null || Request.Files.Count < 1)
                    return BuildReturnScript(funcNum, null, "No file has been sent");

                string fileName = string.Empty;
                SaveAttatchedFile(filesavepath, Request, ref fileName);
                var url = baseUrl + fileName;

            return BuildReturnScript(funcNum, url, null);
            }

            private ContentResult BuildReturnScript(int functionNumber, string url, string errorMessage)
            {
                return Content(
                    string.Format(scriptTag, functionNumber, HttpUtility.JavaScriptStringEncode(url ?? ""), HttpUtility.JavaScriptStringEncode(errorMessage ?? "")),
                    "text/html"
                    );
            }

            private void SaveAttatchedFile(string filepath, HttpRequestBase Request, ref string fileName)
            {
                for (int i = 0; i < Request.Files.Count; i++)
                {
                    var file = Request.Files[i];
                    if (file != null && file.ContentLength > 0)
                    {
                        fileName = Path.GetFileName(file.FileName);
                        string targetPath = Server.MapPath(filepath);
                        if (!Directory.Exists(targetPath))
                        {
                            Directory.CreateDirectory(targetPath);
                        }
                        fileName = Guid.NewGuid() + fileName;
                        string fileSavePath = Path.Combine(targetPath, fileName);
                        file.SaveAs(fileSavePath);
                    }
                }
            }
    }

}
Shaik Matheen
  • 1,233
  • 15
  • 14