Como você pode integrar um navegador / uploader de arquivos personalizado com o CKEditor?

112

A documentação oficial é menos do que clara - qual é a maneira correta de integrar um navegador / uploader de arquivo personalizado com o CKEditor? (v3 - não FCKEditor)

Don Jones
fonte

Respostas:

175

Comece registrando seu navegador / uploader personalizado ao instanciar o CKEditor. Você pode designar URLs diferentes para um navegador de imagem e um navegador de arquivo geral.

<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>

Seu código personalizado receberá um parâmetro GET chamado CKEditorFuncNum. Salve - essa é a sua função de retorno de chamada. Digamos que você coloque em $callback.

Quando alguém selecionar um arquivo, execute este JavaScript para informar ao CKEditor qual arquivo foi selecionado:

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

Onde "url" é o URL do arquivo que eles escolheram. Um terceiro parâmetro opcional pode ser o texto que você deseja exibir em uma caixa de diálogo de alerta padrão, como "arquivo ilegal" ou algo assim. Defina url como uma string vazia se o terceiro parâmetro for uma mensagem de erro.

A aba "upload" do CKEditor irá submeter um arquivo no campo "upload" - em PHP, que vai para $ _FILES ['upload']. O que o CKEditor deseja que seu servidor produza é um bloco JavaScript completo:

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

Novamente, você precisa fornecer esse parâmetro de retorno de chamada, a URL do arquivo e, opcionalmente, uma mensagem. Se a mensagem for uma string vazia, nada será exibido; se a mensagem for um erro, o url deve ser uma string vazia.

A documentação oficial do CKEditor está incompleta em tudo isso, mas se você seguir o acima, ela funcionará como um campeão.

Don Jones
fonte
28
Não posso acreditar que a documentação do desenvolvedor para este processo seja tão esparsa. Obrigado por preencher os detalhes.
4
Essa foi uma ótima informação! Muito melhor do que a documentação oficial.
Jon Romero
2
Muito obrigado! Mas é CKEditorFunNum, não Name = P
emzero
2
@emzero, acho que provavelmente foi CKEditorFuncName, talvez quanto mais CKEditor use CKEditorFuncNum agora. De qualquer forma, a resposta está certa!
Rosdi Kasim
1
Além disso, se você precisar ocultar a "guia Upload" para permitir apenas o upload da imagem, pode usar: CKEDITOR.on ('dialogDefinition', function (ev) {// Retire o nome da caixa de diálogo e sua definição do evento / / data. var dialogName = ev.data.name; var dialogDefinition = ev.data.definition; // Verifique se a definição vem da caixa de diálogo em que // estamos interessados ​​(a caixa de diálogo Link e imagem). if (dialogName = = 'link' || dialogName == 'image') {// remover a guia Upload dialogDefinition.removeContents ('Upload');}});
Kristijan de
10

Acabei de passar pelo processo de aprendizagem sozinho. Eu descobri, mas concordo que a documentação foi escrita de uma forma que foi meio intimidante para mim. O grande momento "aha" para mim foi entender que, para navegar, tudo que o CKeditor faz é abrir uma nova janela e fornecer alguns parâmetros na url. Ele permite que você adicione parâmetros adicionais, mas saiba que você precisará usar encodeURIComponent () em seus valores.

Eu chamo o navegador e o uploader com

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

Para o navegador , na janela aberta (browse.php) você usa php & js para fornecer uma lista de opções e, em seguida, em seu manipulador onclick fornecido, você chama uma função CKeditor com dois argumentos, o url / caminho para a imagem selecionada e CKEditorFuncNum fornecido por CKeditor no url:

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

Simarly, o uploader simplesmente chama a url que você fornece, por exemplo, upload.php , e novamente fornece $ _GET ['CKEditorFuncNum']. O destino é um iframe, então, depois de salvar o arquivo de $ _FILES, você passa seu feedback para o CKeditor da seguinte forma:

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

Abaixo está um script de navegador personalizado simples de entender. Embora não permita que os usuários naveguem no servidor, permite indicar de qual diretório extrair os arquivos de imagem ao chamar o navegador.

É uma codificação bastante básica, por isso deve funcionar em todos os navegadores relativamente modernos.

CKeditor simplesmente abre uma nova janela com o url fornecido

/*          
    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 abaixo para browse.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
fonte
9

Passei um tempo tentando descobrir isso e aqui está o que eu fiz. Eu o dividi de forma muito simples, pois era disso que eu precisava.

Diretamente abaixo da área de texto do ckeditor, insira o arquivo de upload assim >>>>

<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>

'e, em seguida, adicione seu arquivo de upload, aqui está o meu que está escrito em ASP. Se você estiver usando PHP, etc., simplesmente substitua o ASP pelo seu script de upload, mas certifique-se de que a saída da página seja a mesma.

<%@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
fonte
8

Esta é a abordagem que usei. É bastante simples e funciona muito bem.

No diretório raiz do editor CK, há um arquivo chamado config.js

Eu adicionei isto (você não precisa do material de querystring, isto é apenas para nosso gerenciador de arquivos). Eu também incluí alguns skins e mudanças nos botões padrão mostrados:

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']
    ];

};

Então, nosso gerenciador de arquivos chama isso de:

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

Um artigo no zerokspot intitulado Custom filebrowser callbacks in CKEditor 3.0 trata disso. A seção mais relevante é citada abaixo:

Portanto, tudo o que você precisa fazer no navegador de arquivos quando tiver um arquivo selecionado é chamar esse código com o número de retorno de chamada correto (normalmente 1) e a URL do arquivo selecionado:

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

Para o carregador rápido, o processo é bastante semelhante. A princípio pensei que o editor poderia estar ouvindo um código de retorno HTTP 200 e talvez olhar para algum campo de cabeçalho ou algo parecido para determinar a localização do arquivo carregado, mas então - por meio de algum monitoramento Firebug - percebi que tudo isso acontece após um upload é o seguinte código:

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

Se o upload falhou, defina o errorMessagepara alguma string diferente de zero e esvazie o url, e vice-versa em caso de sucesso.

clops
fonte
1
você poderia ter fornecido o url -> zerokspot.com/weblog/2009/09/09/…
Jon Romero
1
Por mais que eu aprecie que você encontrou meu blog, clops, você poderia pelo menos ter vinculado a ele ou apenas vinculado a ele, em vez de copiar / colar a postagem do meu blog.
Horst Gutmann
1
@Jon & @Horst: Obrigado por apontar isso. Se eu cortar algo relevante que precise ser colocado de volta, é só me avisar.
Bill the Lizard
4

Comece registrando seu navegador / uploader personalizado ao instanciar o 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 o arquivo de upload (ckFileUpload.php) e coloque o arquivo de upload no diretório raiz do seu projeto.

// 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>';

A documentação do Ck-editor não está clara depois de fazer um monte de P&D para upload de arquivo personalizado. Finalmente encontrei essa solução. Funciona para mim e espero que seja útil para outras pessoas também.

rahul sharma
fonte
1

Para as pessoas que estão se perguntando sobre uma implementação de Servlet / JSP, veja como fazer isso ... Explicarei o uploadimage abaixo também.

1) Primeiro certifique-se de ter adicionado o filebrowser e a variável uploadimage ao seu arquivo config.js. Faça você também tem a uploadimage e filebrowser pasta dentro da pasta plugins também.

2) Esta parte é onde me tropeçou:

A documentação do site do Ckeditor diz que você precisa usar estes dois 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();
}

O que eles não mencionam é que esses métodos precisam estar em uma página diferente e não na página de onde você está clicando no botão de navegação do servidor .

Portanto, se o ckeditor foi inicializado na página editor.jsp , você precisa criar um navegador de arquivos (com html / css / javascript básico) na página filebrowser.jsp .

editor.jsp (tudo que você precisa é isso em sua tag de script) Esta página abrirá filebrowser.jsp em uma mini janela quando você clicar no botão de navegação do 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 (é o navegador de arquivos personalizado que você construiu, que conterá os métodos mencionados acima)

<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) O 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

Volte para o arquivo config.js para ckeditor e adicione a seguinte linha:

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

Em seguida, você também pode arrastar e soltar arquivos:

   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);
                    }
                }

E isso é tudo pessoal. Espero que ajude alguém.

Jonathan Laliberte
fonte