¿Cómo se puede integrar un navegador / cargador de archivos personalizado con CKEditor?

112

La documentación oficial es menos clara: ¿cuál es la forma correcta de integrar un navegador / cargador de archivos personalizado con CKEditor? (v3 - no FCKEditor)

Don Jones
fuente

Respuestas:

175

Comience registrando su navegador / cargador personalizado cuando cree una instancia de CKEditor. Puede designar diferentes URL para un navegador de imágenes frente a un navegador de archivos general.

<script type="text/javascript">
CKEDITOR.replace('content', {
    filebrowserBrowseUrl : '/browser/browse/type/all',
    filebrowserUploadUrl : '/browser/upload/type/all',
    filebrowserImageBrowseUrl : '/browser/browse/type/image',
filebrowserImageUploadUrl : '/browser/upload/type/image',
    filebrowserWindowWidth  : 800,
    filebrowserWindowHeight : 500
});
</script>

Su código personalizado recibirá un parámetro GET llamado CKEditorFuncNum. Guárdelo, esa es su función de devolución de llamada. Digamos que lo pones en $callback.

Cuando alguien selecciona un archivo, ejecute este JavaScript para informar a CKEditor qué archivo se seleccionó:

window.opener.CKEDITOR.tools.callFunction(<?php echo $callback; ?>,url)

Donde "url" es la URL del archivo que eligieron. Un tercer parámetro opcional puede ser el texto que desea que se muestre en un cuadro de diálogo de alerta estándar, como "archivo ilegal" o algo así. Establezca la URL en una cadena vacía si el tercer parámetro es un mensaje de error.

La pestaña "cargar" de CKEditor enviará un archivo en el campo "cargar" - en PHP, que va a $ _FILES ['cargar']. Lo que CKEditor quiere que su servidor genere es un bloque completo de JavaScript:

$output = '<html><body><script type="text/javascript">window.parent.CKEDITOR.tools.callFunction('.$callback.', "'.$url.'","'.$msg.'");</script></body></html>';
echo $output;

Nuevamente, debe darle ese parámetro de devolución de llamada, la URL del archivo y, opcionalmente, un mensaje. Si el mensaje es una cadena vacía, no se mostrará nada; si el mensaje es un error, la URL debe ser una cadena vacía.

La documentación oficial de CKEditor está incompleta sobre todo esto, pero si sigue lo anterior, funcionará como un campeón.

Don Jones
fuente
29
No puedo creer que la documentación para desarrolladores de este proceso sea tan escasa. Gracias por completar los detalles.
4
¡Esa fue una gran información! Mucho mejor que la documentación oficial.
Jon Romero
2
¡Muchas gracias! Pero es CKEditorFunNum, no Name = P
emzero
2
@emzero, creo que probablemente fue CKEditorFuncName, tal vez cuanto más CKEditor usa CKEditorFuncNum ahora. De todos modos, la respuesta es acertada.
Rosdi Kasim
1
Además, si necesita ocultar la "pestaña Cargar" para permitir solo la carga de la imagen, puede usar: CKEDITOR.on ('dialogDefinition', function (ev) {// Tome el nombre del diálogo y su definición del evento / / data. var dialogName = ev.data.name; var dialogDefinition = ev.data.definition; // Verifica si la definición es del diálogo que estamos // interesados ​​(el diálogo de enlace e imagen). if (dialogName = = 'link' || dialogName == 'image') {// eliminar pestaña Cargar dialogDefinition.removeContents ('Cargar');}});
Kristijan
10

Yo solo pasé por el proceso de aprendizaje. Lo descubrí, pero estoy de acuerdo en que la documentación está escrita de una manera que me intimidaba. El gran momento "ajá" para mí fue entender que para navegar, todo lo que CKeditor hace es abrir una nueva ventana y proporcionar algunos parámetros en la URL. Le permite agregar parámetros adicionales, pero tenga en cuenta que deberá usar encodeURIComponent () en sus valores.

Llamo al navegador y al cargador con

CKEDITOR.replace( 'body',  
{  
    filebrowserBrowseUrl: 'browse.php?type=Images&dir=' +  
        encodeURIComponent('content/images'),  
    filebrowserUploadUrl: 'upload.php?type=Files&dir=' +  
        encodeURIComponent('content/images')  
}

Para el navegador , en la ventana abierta (navegar.php) usa php & js para proporcionar una lista de opciones y luego, en el controlador onclick proporcionado, llama a una función CKeditor con dos argumentos, la url / ruta a la imagen seleccionada y CKEditorFuncNum proporcionado por CKeditor en la URL:

function myOnclickHandler(){  
//..    
    window.opener.CKEDITOR.tools.callFunction(<?php echo $_GET['CKEditorFuncNum']; ?>, pathToImage);  
    window.close();
}       

De manera similar, el cargador simplemente llama a la URL que proporcionas, por ejemplo, upload.php , y nuevamente proporciona $ _GET ['CKEditorFuncNum']. El objetivo es un iframe, por lo que, después de guardar el archivo de $ _FILES, pasa sus comentarios a CKeditor de la siguiente manera:

$funcNum = $_GET['CKEditorFuncNum'];  
exit("<script>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath', '$errorMessage');</script>");  

A continuación se muestra un script de navegador personalizado fácil de entender. Si bien no permite que los usuarios naveguen por el servidor, sí le permite indicar de qué directorio extraer los archivos de imagen al llamar al navegador.

Todo es una codificación bastante básica, por lo que debería funcionar en todos los navegadores relativamente modernos.

CKeditor simplemente abre una nueva ventana con la URL proporcionada

/*          
    in CKeditor **use encodeURIComponent()** to add dir param to the filebrowserBrowseUrl property

    Replace content/images with directory where your images are housed.
*/          
        CKEDITOR.replace( 'editor1', {  
            filebrowserBrowseUrl: '**browse.php**?type=Images&dir=' + encodeURIComponent('content/images'),  
            filebrowserUploadUrl: 'upload.php?type=Files&dir=' + encodeURIComponent('content/images') 
        });   

// ========= código completo a continuación para navegar.php

<?php  
header("Content-Type: text/html; charset=utf-8\n");  
header("Cache-Control: no-cache, must-revalidate\n");  
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");  

// e-z params  
$dim = 150;         /* image displays proportionally within this square dimension ) */  
$cols = 4;          /* thumbnails per row */
$thumIndicator = '_th'; /* e.g., *image123_th.jpg*) -> if not using thumbNails then use empty string */  
?>  
<!DOCTYPE html>  
<html>  
<head>  
    <title>browse file</title>  
    <meta charset="utf-8">  

    <style>  
        html,  
        body {padding:0; margin:0; background:black; }  
        table {width:100%; border-spacing:15px; }  
        td {text-align:center; padding:5px; background:#181818; }  
        img {border:5px solid #303030; padding:0; verticle-align: middle;}  
        img:hover { border-color:blue; cursor:pointer; }  
    </style>  

</head>  


<body>  

<table>  

<?php  

$dir = $_GET['dir'];    

$dir = rtrim($dir, '/'); // the script will add the ending slash when appropriate  

$files = scandir($dir);  

$images = array();  

foreach($files as $file){  
    // filter for thumbNail image files (use an empty string for $thumIndicator if not using thumbnails )
    if( !preg_match('/'. $thumIndicator .'\.(jpg|jpeg|png|gif)$/i', $file) )  
        continue;  

    $thumbSrc = $dir . '/' . $file;  
    $fileBaseName = str_replace('_th.','.',$file);  

    $image_info = getimagesize($thumbSrc);  
    $_w = $image_info[0];  
    $_h = $image_info[1]; 

    if( $_w > $_h ) {       // $a is the longer side and $b is the shorter side
        $a = $_w;  
        $b = $_h;  
    } else {  
        $a = $_h;  
        $b = $_w;  
    }     

    $pct = $b / $a;     // the shorter sides relationship to the longer side

    if( $a > $dim )   
        $a = $dim;      // limit the longer side to the dimension specified

    $b = (int)($a * $pct);  // calculate the shorter side

    $width =    $_w > $_h ? $a : $b;  
    $height =   $_w > $_h ? $b : $a;  

    // produce an image tag
    $str = sprintf('<img src="%s" width="%d" height="%d" title="%s" alt="">',   
        $thumbSrc,  
        $width,  
        $height,  
        $fileBaseName  
    );  

    // save image tags in an array
    $images[] = str_replace("'", "\\'", $str); // an unescaped apostrophe would break js  

}

$numRows = floor( count($images) / $cols );  

// if there are any images left over then add another row
if( count($images) % $cols != 0 )  
    $numRows++;  


// produce the correct number of table rows with empty cells
for($i=0; $i<$numRows; $i++)   
    echo "\t<tr>" . implode('', array_fill(0, $cols, '<td></td>')) . "</tr>\n\n";  

?>  
</table>  


<script>  

// make a js array from the php array
images = [  
<?php   

foreach( $images as $v)  
    echo sprintf("\t'%s',\n", $v);  

?>];  

tbl = document.getElementsByTagName('table')[0];  

td = tbl.getElementsByTagName('td');  

// fill the empty table cells with data
for(var i=0; i < images.length; i++)  
    td[i].innerHTML = images[i];  


// event handler to place clicked image into CKeditor
tbl.onclick =   

    function(e) {  

        var tgt = e.target || event.srcElement,  
            url;  

        if( tgt.nodeName != 'IMG' )  
            return;  

        url = '<?php echo $dir;?>' + '/' + tgt.title;  

        this.onclick = null;  

        window.opener.CKEDITOR.tools.callFunction(<?php echo $_GET['CKEditorFuncNum']; ?>, url);  

        window.close();  
    }  
</script>  
</body>  
</html>            
Tim
fuente
9

Pasé un tiempo tratando de resolver esto y esto es lo que hice. Lo he desglosado de manera muy simple, ya que eso es lo que necesitaba.

Directamente debajo del área de texto de su ckeditor, ingrese el archivo de carga como este >>>>

<form action="welcomeeditupload.asp" method="post" name="deletechecked">
    <div align="center">
        <br />
        <br />
        <label></label>
        <textarea class="ckeditor" cols="80" id="editor1" name="editor1" rows="10"><%=(rslegschedule.Fields.Item("welcomevar").Value)%></textarea>
        <script type="text/javascript">
        //<![CDATA[
            CKEDITOR.replace( 'editor1',
            {
                filebrowserUploadUrl : 'updateimagedone.asp'
            });
        //]]>
        </script>
        <br />
        <br />
        <br />
        <input type="submit" value="Update">
    </div>
</form>

'y luego agregue su archivo de carga, aquí está el mío que está escrito en ASP. Si está utilizando PHP, etc., simplemente reemplace el ASP con su script de carga, pero asegúrese de que la página muestre lo mismo.

<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<%
    if Request("CKEditorFuncNum")=1 then
        Set Upload = Server.CreateObject("Persits.Upload")
        Upload.OverwriteFiles = False
        Upload.SetMaxSize 5000000, True
        Upload.CodePage = 65001

        On Error Resume Next
        Upload.Save "d:\hosting\belaullach\senate\legislation"

        Dim picture
        For Each File in Upload.Files
            Ext = UCase(Right(File.Path, 3))
            If Ext <> "JPG" Then
                    If Ext <> "BMP" Then
                    Response.Write "File " & File.Path & " is not a .jpg or .bmp file." & "<BR>"
                    Response.write "You can only upload .jpg or .bmp files." & "<BR>" & "<BR>"
                    End if
            Else
                File.SaveAs Server.MapPath(("/senate/legislation") & "/" & File.fileName)
                f1=File.fileName
            End If
        Next
    End if

    fnm="/senate/legislation/"&f1
    imgop = "<html><body><script type=""text/javascript"">window.parent.CKEDITOR.tools.callFunction('1','"&fnm&"');</script></body></html>;"
    'imgop="callFunction('1','"&fnm&"',"");"
    Response.write imgop
%>
elliott benzle
fuente
8

Este es el enfoque que he usado. Es bastante sencillo y funciona bien.

En el directorio raíz del editor CK hay un archivo llamado config.js

Agregué esto (no necesitas las cadenas de consulta, esto es solo para nuestro administrador de archivos). También incluí algunos aspectos y cambios de los botones predeterminados que se muestran:

CKEDITOR.editorConfig = function(config) {

    config.skin = 'v2';
    config.startupFocus = false;
    config.filebrowserBrowseUrl = '/admin/content/filemanager.aspx?path=Userfiles/File&editor=FCK';
    config.filebrowserImageBrowseUrl = '/admin/content/filemanager.aspx?type=Image&path=Userfiles/Image&editor=FCK';
    config.toolbar_Full =
    [
        ['Source', '-', 'Preview', '-'],
        ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Print', 'SpellChecker'], //, 'Scayt' 
        ['Undo', 'Redo', '-', 'Find', 'Replace', '-', 'SelectAll', 'RemoveFormat'],
        '/',
        ['Bold', 'Italic', 'Underline', 'Strike', '-', 'Subscript', 'Superscript'],
        ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Blockquote'],
        ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
        ['Link', 'Unlink', 'Anchor'],
        ['Image', 'Flash', 'Table', 'HorizontalRule', 'SpecialChar'],
        '/',
        ['Styles', 'Format', 'Templates'],
        ['Maximize', 'ShowBlocks']
    ];

};

Entonces, nuestro administrador de archivos llama a esto:

opener.SetUrl('somefilename');
ScottE
fuente
7

Un artículo en zerokspot titulado Devoluciones de llamada personalizadas del navegador de archivos en CKEditor 3.0 maneja esto. La sección más relevante se cita a continuación:

Entonces, todo lo que tiene que hacer desde el explorador de archivos cuando tiene un archivo seleccionado es llamar a este código con el número de devolución de llamada correcto (normalmente 1) y la URL del archivo seleccionado:

window.opener.CKEDITOR.tools.callFunction(CKEditorFuncNum,url);

Para el cargador rápido, el proceso es bastante similar. Al principio pensé que el editor podría estar escuchando un código de retorno HTTP 200 y tal vez buscar en algún campo de encabezado o algo así para determinar la ubicación del archivo cargado, pero luego, a través de un monitoreo de Firebug, noté que todo eso sucede después de una carga aparece el siguiente código:

<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction(CKEditorFuncNum,url, errorMessage); </script>

Si la carga falló, establezca el valor errorMessageen una cadena de longitud distinta de cero y vacíe la URL, y viceversa si se realiza correctamente.

clops
fuente
1
podría haber dado la url -> zerokspot.com/weblog/2009/09/09/…
Jon Romero
1
Por mucho que aprecio que hayas encontrado mi blog, clops, al menos podrías haberlo vinculado o simplemente vinculado a él, en lugar de copiar / pegar mi publicación de blog.
Horst Gutmann
1
@Jon & @Horst: Gracias por señalar esto. Si elimino algo relevante que deba volver a introducirse, házmelo saber.
Bill the Lizard
4

Comience registrando su navegador / cargador personalizado cuando cree una instancia de CKEditor.

<script type="text/javascript">
CKEDITOR.replace('content', {
    filebrowserUploadUrl: "Upload File Url",//http://localhost/phpwork/test/ckFileUpload.php
    filebrowserWindowWidth  : 800,
    filebrowserWindowHeight : 500
});
</script>

Código para el archivo de carga (ckFileUpload.php) y coloque el archivo de carga en el directorio raíz de su proyecto.

// HERE SET THE PATH TO THE FOLDERS FOR IMAGES AND AUDIO ON YOUR SERVER (RELATIVE TO THE ROOT OF YOUR WEBSITE ON SERVER)

$upload_dir = array(
 'img'=> '/phpwork/test/uploads/editor-images/',
 'audio'=> '/phpwork/ezcore_v1/uploads/editor-images/'
);

// HERE PERMISSIONS FOR IMAGE
$imgset = array(
 'maxsize' => 2000,     // maximum file size, in KiloBytes (2 MB)
 'maxwidth' => 900,     // maximum allowed width, in pixels
 'maxheight' => 800,    // maximum allowed height, in pixels
 'minwidth' => 10,      // minimum allowed width, in pixels
 'minheight' => 10,     // minimum allowed height, in pixels
 'type' => array('bmp', 'gif', 'jpg', 'jpeg', 'png'),  // allowed extensions
);

// HERE PERMISSIONS FOR AUDIO
$audioset = array(
 'maxsize' => 20000,    // maximum file size, in KiloBytes (20 MB)
 'type' => array('mp3', 'ogg', 'wav'),  // allowed extensions
);

// If 1 and filename exists, RENAME file, adding "_NR" to the end of filename (name_1.ext, name_2.ext, ..)
// If 0, will OVERWRITE the existing file
define('RENAME_F', 1);

$re = '';
if(isset($_FILES['upload']) && strlen($_FILES['upload']['name']) >1) {
  define('F_NAME', preg_replace('/\.(.+?)$/i', '', basename($_FILES['upload']['name'])));  //get filename without extension

  // get protocol and host name to send the absolute image path to CKEditor
  $protocol = !empty($_SERVER['HTTPS']) ? 'https://' : 'http://';
  $site = $protocol. $_SERVER['SERVER_NAME'] .'/';
  $sepext = explode('.', strtolower($_FILES['upload']['name']));
  $type = end($sepext);    // gets extension
  $upload_dir = in_array($type, $imgset['type']) ? $upload_dir['img'] : $upload_dir['audio'];
  $upload_dir = trim($upload_dir, '/') .'/';

  //checkings for image or audio
  if(in_array($type, $imgset['type'])){
    list($width, $height) = getimagesize($_FILES['upload']['tmp_name']);  // image width and height
    if(isset($width) && isset($height)) {
      if($width > $imgset['maxwidth'] || $height > $imgset['maxheight']) $re .= '\\n Width x Height = '. $width .' x '. $height .' \\n The maximum Width x Height must be: '. $imgset['maxwidth']. ' x '. $imgset['maxheight'];
      if($width < $imgset['minwidth'] || $height < $imgset['minheight']) $re .= '\\n Width x Height = '. $width .' x '. $height .'\\n The minimum Width x Height must be: '. $imgset['minwidth']. ' x '. $imgset['minheight'];
      if($_FILES['upload']['size'] > $imgset['maxsize']*1000) $re .= '\\n Maximum file size must be: '. $imgset['maxsize']. ' KB.';
    }
  }
  else if(in_array($type, $audioset['type'])){
    if($_FILES['upload']['size'] > $audioset['maxsize']*1000) $re .= '\\n Maximum file size must be: '. $audioset['maxsize']. ' KB.';
  }
  else $re .= 'The file: '. $_FILES['upload']['name']. ' has not the allowed extension type.';

  //set filename; if file exists, and RENAME_F is 1, set "img_name_I"
  // $p = dir-path, $fn=filename to check, $ex=extension $i=index to rename
  function setFName($p, $fn, $ex, $i){
    if(RENAME_F ==1 && file_exists($p .$fn .$ex)) return setFName($p, F_NAME .'_'. ($i +1), $ex, ($i +1));
    else return $fn .$ex;
  }

  $f_name = setFName($_SERVER['DOCUMENT_ROOT'] .'/'. $upload_dir, F_NAME, ".$type", 0);
  $uploadpath = $_SERVER['DOCUMENT_ROOT'] .'/'. $upload_dir . $f_name;  // full file path

  // If no errors, upload the image, else, output the errors
  if($re == '') {
    if(move_uploaded_file($_FILES['upload']['tmp_name'], $uploadpath)) {
      $CKEditorFuncNum = $_GET['CKEditorFuncNum'];
      $url = $site. $upload_dir . $f_name;
      $msg = F_NAME .'.'. $type .' successfully uploaded: \\n- Size: '. number_format($_FILES['upload']['size']/1024, 2, '.', '') .' KB';
      $re = in_array($type, $imgset['type']) ? "window.parent.CKEDITOR.tools.callFunction($CKEditorFuncNum, '$url', '$msg')"  //for img
       : 'var cke_ob = window.parent.CKEDITOR; for(var ckid in cke_ob.instances) { if(cke_ob.instances[ckid].focusManager.hasFocus) break;} cke_ob.instances[ckid].insertHtml(\'<audio src="'. $url .'" controls></audio>\', \'unfiltered_html\'); alert("'. $msg .'"); var dialog = cke_ob.dialog.getCurrent();  dialog.hide();';
    }
    else $re = 'alert("Unable to upload the file")';
  }
  else $re = 'alert("'. $re .'")';
}

@header('Content-type: text/html; charset=utf-8');
echo '<script>'. $re .';</script>';

La documentación de Ck-editor no está clara después de realizar una gran cantidad de I + D para cargar archivos personalizados, finalmente encontré esta solución. Funciona para mí y espero que también sea útil para otros.

Rahul Sharma
fuente
1

Para las personas que se preguntan acerca de una implementación de Servlet / JSP, así es como lo hacen ... También explicaré la imagen de carga a continuación.

1) Primero asegúrese de haber agregado el navegador de archivos y la variable uploadimage a su archivo config.js. Haga que también tenga la carpeta uploadimage y filebrowser dentro de la carpeta de complementos.

2) Esta parte es donde me hizo tropezar:

La documentación del sitio web de Ckeditor dice que debe utilizar estos dos métodos:

function getUrlParam( paramName ) {
    var reParam = new RegExp( '(?:[\?&]|&)' + paramName + '=([^&]+)', 'i' );
    var match = window.location.search.match( reParam );
    return ( match && match.length > 1 ) ? match[1] : null;
}
function returnFileUrl() {
    var funcNum = getUrlParam( 'CKEditorFuncNum' );
    var fileUrl = 'https://patiliyo.com/wp-content/uploads/2017/07/ruyada-kedi-gormek.jpg';
    window.opener.CKEDITOR.tools.callFunction( funcNum, fileUrl );
    window.close();
}

Lo que no mencionan es que estos métodos deben estar en una página diferente y no en la página desde la que está haciendo clic en el botón del servidor de búsqueda.

Entonces, si ha inicializado ckeditor en page editor.jsp, entonces necesita crear un navegador de archivos (con html básico / css / javascript) en la página filebrowser.jsp .

editor.jsp (todo lo que necesita es esto en su etiqueta de script) Esta página abrirá filebrowser.jsp en una mini ventana cuando haga clic en el botón de buscar servidor.

CKEDITOR.replace( 'editor', {
    filebrowserBrowseUrl: '../filebrowser.jsp', //jsp page with jquery to call servlet and get image files to view
    filebrowserUploadUrl: '../UploadImage', //servlet

});

filebrowser.jsp (es el navegador de archivos personalizado que construyó y que contendrá los métodos mencionados anteriormente)

<head>
<script src="../../ckeditor/ckeditor.js"></script>
</head>
<body>
<script>


function getUrlParam( paramName ) {
    var reParam = new RegExp( '(?:[\?&]|&)' + paramName + '=([^&]+)', 'i' );
    var match = window.location.search.match( reParam );
    return ( match && match.length > 1 ) ? match[1] : null;
}

function returnFileUrl() {
    var funcNum = getUrlParam( 'CKEditorFuncNum' );
var fileUrl = 'https://patiliyo.com/wp-content/uploads/2017/07/ruyada-kedi-gormek.jpg';
    window.opener.CKEDITOR.tools.callFunction( funcNum, fileUrl );
    window.close();
}


//when this window opens it will load all the images which you send from the FileBrowser Servlet. 
getImages();
function getImages(){
    $.get("../FileBrowser", function(responseJson) {    
        //do something with responseJson (like create <img> tags and update the src attributes) 
    });
}

   //you call this function and pass 'fileUrl' when user clicks on an image that you loaded into this window from a servlet
returnFileUrl();
</script>
</body>

3) El Servlet FileBrowser

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Images i = new Images();
    List<ImageObject> images = i.getImages(); //get images from your database or some cloud service or whatever (easier if they are in a url ready format)
    String json = new Gson().toJson(images);
    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

4) Servlet UploadImage

Regrese a su archivo config.js para ckeditor y agregue la siguiente línea:

//https://docs.ckeditor.com/ckeditor4/latest/guide/dev_file_upload.html
config.uploadUrl = '/UploadImage';

Luego puede arrastrar y soltar archivos también:

   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


                Images i = new Images();

   //do whatever you usually do to upload your image to your server (in my case i uploaded to google cloud storage and saved the url in a database. 

   //Now this part is important. You need to return the response in json format. And it has to look like this:

//      https://docs.ckeditor.com/ckeditor4/latest/guide/dev_file_upload.html
//      response must be in this format:
//      {
//          "uploaded": 1,
//          "fileName": "example.png",
//          "url": "https://www.cats.com/example.png"
//      }

                    String image = "https://www.cats.com/example.png";
                        ImageObject objResponse = i.getCkEditorObjectResponse(image);
                        String json = new Gson().toJson(objResponse);
                        response.setContentType("application/json");
                        response.setCharacterEncoding("UTF-8");
                        response.getWriter().write(json);
                    }
                }

Y eso es todo amigos. Espero que ayude a alguien.

Jonathan Laliberte
fuente