A CKEditor File Browser For ASP.NET Web Pages

4.9 (10 votes)

CKEditor is one of the most popular rich text editors available. Out of the box, there is no file browser to help with selecting images, but you can purchase an add-on from them - CKFinder. Alternatively, you can build your own file browser component.

By default, if you click the Image button in CKEditor, you are presented with a dialogue box that requires you to enter a url for the image you want to insert. For web developers an other users with a technical bent, that shouldn't pose too many problems, but the average user won't have a clue as to what is required. What they need is a way to select an image and to have its url automatically populate the dialogue. CKEditor exposes an API that enables developers to plug in their own custom file browser to enable this.

At its simplest, a file browser can present a list of files and provide a means by which the user can indicate which one they would like to use. However, this approach would require that the user can identify which image they would like to select purely from its file name. Once any collection of image files grows, it is unlikely that the user will be able to associate images with file names unless some kind of supplementary indexing system was employed. A much more user-friendly solution would be to provide the user with a collection of thumbnails of images from which they can make their selection. The workflow is as follows:

  1. User clicks a button to browse images on the server
  2. User is presented with a list of directories that contain images from which they can select one
  3. The images in the selected directory are presented to the user in thumbnail form
  4. User can select one image by clicking it and the dialogue is populated with their selection

So you need to begin with some code to generate thumbnails of reasonable quality for display. The following code is added to a file called ThumbNails.cshtml which is placed in the App_Code folder:

@using System;
@using System.Drawing;
@using System.Drawing.Drawing2D;
@using System.IO;
@functions {
    public static byte[] GenerateTumbnail(string image, double thumbWidth) {
        try {
            using (var originalImage = Image.FromFile(image)) {
                var oWidth = originalImage.Width;
                var oHeight = originalImage.Height;
                var thumbHeight = oWidth > thumbWidth ? (thumbWidth / oWidth) * oHeight : oHeight;
                thumbWidth = oWidth > thumbWidth ? thumbWidth : oWidth;
                using (var bmp = new Bitmap((int)thumbWidth, (int)thumbHeight)) {
                    bmp.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
                    using (var graphic = Graphics.FromImage(bmp)) {
                        graphic.SmoothingMode = SmoothingMode.AntiAlias;
                        graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;

                        var rectangle = new Rectangle(0, 0, (int)thumbWidth, (int)thumbHeight);
                        graphic.DrawImage(originalImage, rectangle, 0, 0, oWidth, oHeight, GraphicsUnit.Pixel);
                        var ms = new MemoryStream();
                        bmp.Save(ms, originalImage.RawFormat);
                        return ms.GetBuffer();
        catch (Exception ex) {
            throw (ex);

This method picks up the the original image that is passed into it, and reduces it in size if it exceeds the width passed in as the second argument. It returns a byte array, so the new image is not stored on disk. Next, you need some code that passes in the image and thumbnail width and can do something meaningful with the byte array that is returned. This code forms Thumb.cshtml which resides in the root of the site:

    if (Request["image"].IsEmpty()) {
    var image = Path.Combine(Server.MapPath("~/Media/"), Server.UrlDecode(Request["image"]));
    var thumbWidth = 128D;
    var buffer = ThumbNails.GenerateTumbnail(image, thumbWidth);
    Response.ContentType = string.Format("image/{0}", Path.GetExtension(image).Trim(new[]{'.'}));
    Response.OutputStream.Write(buffer, 0, buffer.Length);

This file acts as a handler. When it is requested, it takes the image file name from the query string and uses the GenerateThumbnail function to create the thumb image and then write it to the browser. For a handler file like this to work, it needs to be set as the src of an image element. That happens in ImageViewer.cshtml:

    Layout = null;
    var directory = new DirectoryInfo(Path.Combine(Server.MapPath("~/Media"), Request["directory"]));
@foreach (var file in directory.GetFilesByExtensions(".png", ".gif", ".jpg")) {
    <div class="thumbnail">
        <img src="/Thumb/?image=@directory.Name\@file.Name" alt="thumb" title="@directory.Name/@file.Name" />

This file is responsible for locating the selected directory, represented by the value passed in the query string, and then obtaining all files that have the specified extensions and then displaying their thumbnail version. The url of the image is set as the value of the title attribute. This is visible to the user as a tooltip when they hover over an image, and is used later to populate the CKEditor image dialogue. GetFilesByExtensions is a custom extension method. It lives in a class file called FileExtensions.cs which is placed in the App_Code folder:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public static class FileExtensions
    public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo directoryInfo, params string[] extensions) {
        var allowedExtensions = new HashSet<string>(extensions, StringComparer.OrdinalIgnoreCase);
        return directoryInfo.EnumerateFiles().Where(f => allowedExtensions.Contains(f.Extension));

The main file is called FileBrowser.cshtml. It is the file that gets called when the user clicks the insert image icon in CKEditor.

    Layout = null;
    var media = new DirectoryInfo(Server.MapPath("~/Media"));
        <title>Media Browser</title>
        <link href="~/Content/StyleSheet.css" type="text/css" rel="stylesheet" />
        <script src="/Scripts/jquery.js" type="text/javascript"></script>
        <script src="/Scripts/ckeditor/ckeditor.js" type="text/javascript"></script>
        <script type="text/javascript">
            var funcNum = @(Request["CKEditorFuncNum"] + ";")
            $(function() {
                $('li').click(function() {
                    $('#fileExplorer').load('/ImageViewer?directory=' + encodeURIComponent($(this).text()));
                }).hover(function() {
                    $(this).css('cursor', 'pointer');
                $('#fileExplorer').on('click', 'img', function () {
                    var fileUrl = '/Media/' + $(this).attr('title');
                    window.opener.CKEDITOR.tools.callFunction(funcNum, fileUrl);
                }).hover(function() {
                    $(this).css('cursor', 'pointer');
        <div id="folderExplorer">
            @foreach (var dir in media.EnumerateDirectories().Where(d => d.GetFilesByExtensions(".png", ".gif", ".jpg").Any())) {
       <div id="fileExplorer"></div>

The main images folder is called Media, and images are stored in subfolders. These are displayed in a list. Some jQuery is used to set the cursor to a pointer (hand) when you hover over the list items, indicating that they are clickable. When they are clicked, the empty fileExplorer div is loaded with the result of a request to ImageViewer.cshtml - which is the file that calls Thumb.cshtml to display thumbnail versions of the contents of the selected directory.

The next block of jQuery applies a click event handler to any image that appears in the fileExplorer div. It extracts the url of the image being clicked from its title attribute. It passes that value along with another originally sent to the FileBrowser file by CKEditor back to the editor so that it knows you are selecting a file. The url of the file is applied to the appropriate dialogue text box and then the filebrowser window is closed.

All you need to do now is tell CKEditor that you have a file browser, and where it is. You can do that in the file that features the editor. Here's a minimal file that only displays the editor and configures the file browser:


<!DOCTYPE html>

<html lang="en">
        <meta charset="utf-8" />
        <title>CKEditor File Browser FOR ASP.NET Web Pages</title>
        <link href="~/Content/StyleSheet.css" type="text/css" rel="stylesheet" />
        <script type="text/javascript" src="~/Scripts/jquery.js"></script>
        <script type="text/javascript" src="~/Scripts/ckeditor/ckeditor.js"></script>
            $(function () {
                CKEDITOR.replace('Content', {
                    filebrowserBrowseUrl: '/FileBrowser',
                    filebrowserWindowWidth: 800,
                    filebrowserWindowHeight: 600
        <div id="form">
            <form method="post">
                    <input type="submit" />

The file browser configuration requires a url to be passed to the filebrowserBrowseUrl parameter, and then optionally a height and width for the window that will open to display the resource at the specified url. If you do not specify a height or width, the default values of 80% of the available screen width, and 70% of the available height will be used.

This example, which is available at GitHub assumes that the images are in sub folders of the Media folder. The download also includes a version that works with just one images folder. You can access that version by downloading and running the site and requesting Default2.cshtml.


Date Posted:
Last Updated:
Posted by:
Total Views to date: 27688


- Andrew Davis

Hi Mike,
you can replace the 'GenerateTumbnail' method with new 'WebImage' class found in 'System.Web.Helpers'. This will also enable you to do all the resizing and cropping in a fluent manner.

- Mike


I decided against using the WebImage helper as the quality of the resulting image is not very good.

- Handy


Is there an example to use this on asp.net web forms ?

- Mesut

I used your tutorial in my site, then I saw that you used TinyMCE in your CMS. Could you please prepare a tutorial for TinyMCE?

- Mike


I use CKEditor in the CMS. I've never really looked at TinyMCE.

Recent Comments

Rajasekar 24/11/2015 12:27
In response to Import Data From Excel to Access with ASP.NET
While use this code i'm facing on error: "Unrecognized Database format C:\mydabase.accdb" can any...

Parmod 24/11/2015 07:28
In response to ASP.NET 5 Project Basics
For a new learner (Fresher) in ASP.NET there is a issue Fresher have to learn two types of , old...

Robert 22/11/2015 21:35
In response to ASP.NET 5 By Numbers
I have to agree fully with Paul, this does sound like an entire mis-mash of technologies. Sort of in...

Christian 21/11/2015 15:46
In response to MVC 5 with EF 6 in Visual Basic - Creating an Entity Framework Data Model
Many thanks Mike to introduce me in the EF6 Code First way of thinking. Exactly what I need for my...

ax plains 20/11/2015 16:29
In response to Examining the Details and Delete Methods
Hello, really great tutorial for a beginner like me! Is it possible to have an explanation on how a...

Abdul Latif 20/11/2015 14:42
In response to Reading Excel Files Without Saving To Disk In ASP.NET
Could anyone please help me, I am getting : "OfficeOpenXml.ExcelPackage" does not contain a for...

Thomas 20/11/2015 09:44
In response to Cheat Sheet - .NET Framework Exceptions
Hey Mike, nice list. I've also checked your article on how you created the list, but is there any to...

Pramod Gagare 19/11/2015 11:18
In response to Date Formatting in C#

Robby 19/11/2015 08:16
In response to WebMatrix - Database Helpers for IN Clauses
Would it also be possible to override the default query and querysingle methods to include the azure...

Menja 18/11/2015 08:28
In response to Sessions and Shopping Carts
Thank you for a perfect description and that you show all the screenshot at the same time!!! It a...