Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CKEditor 5 Image Upload Issues

I'm using ckeditor5 into my project. I have to support image upload so I have search and followed this stackoverflow article.

I have created an uploadAdapter which is:

class UploadAdapter {

constructor( loader, url, t ) {
    this.loader = loader;
    this.url = url;
    this.t = t;
}

upload() {
    return new Promise( ( resolve, reject ) => {
        this._initRequest();
        this._initListeners( resolve, reject );
        this._sendRequest();
    } );
}

abort() {
    if ( this.xhr ) {
        this.xhr.abort();
    }
}

_initRequest() {
    const xhr = this.xhr = new XMLHttpRequest();

    xhr.open( 'POST', this.url, true );
    xhr.responseType = 'json';
}

_initListeners( resolve, reject ) {
    const xhr = this.xhr;
    const loader = this.loader;
    const t = this.t;
    const genericError = t( 'Cannot upload file:' ) + ` ${ loader.file.name }.`;

    xhr.addEventListener( 'error', () => reject( genericError ) );
    xhr.addEventListener( 'abort', () => reject() );
    xhr.addEventListener( 'load', () => {
        const response = xhr.response;

        if ( !response || !response.uploaded ) {
            return reject( response && response.error && response.error.message ? response.error.message : genericError );
        }
        resolve( {
            default: response.url
        } );
    } );

    if ( xhr.upload ) {
        xhr.upload.addEventListener( 'progress', evt => {
            if ( evt.lengthComputable ) {
                loader.uploadTotal = evt.total;
                loader.uploaded = evt.loaded;
            }
        } );
    }
}

_sendRequest() {
    const data = new FormData();
    data.append( 'upload', this.loader.file );
    this.xhr.send( data );
}
}

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
export default class GappUploadAdapter extends Plugin {
    static get requires() {
        return [ FileRepository ];
    }

    static get pluginName() {
        return 'GappUploadAdapter';
    }

    init() {
        const url = this.editor.config.get( 'gapp.uploadUrl' );

        if ( !url ) {
            return;
        }

        this.editor.plugins.get( FileRepository ).createUploadAdapter = loader => new UploadAdapter( loader, url, this.editor.t );
    }
}

Now this is explained. I have 2 issues.

  1. Once uploaded ( my upload on server is working fine and returning a valid url in format {default: url}, why is my image content inserted as data-uri and not in url as for easy image demo here. I want my image to be url like.
  2. I would like to listen for a kind of success upload image ( with image id retrieved from upload server call ) to insert some content in my page. How to proceed ? enter image description here enter image description here

Thanks for help.

PS: I'm building ckeditor with command 'npm run build' from git repo cloned from https://github.com/ckeditor/ckeditor5-build-classic

EDIT: Thanks to accepted response, I saw that I was wrong in returned data. I was not returning any URL in my uploader front end which was causing editor image to stay in img-data way. Once valid URL was returned, it was parsed automatically and my editor image was containing a valid url.

image descr

like image 503
franchez Avatar asked Nov 20 '18 16:11

franchez


1 Answers

If the data-uri is still used after successful upload I would assume that server response was not processed correctly and the received url could not be retrieved. I have tested adapter code you provided and it works fine (with CKFinder on server side). I would check how the upload server response looks and if it can be correctly parsed.

When using CKFinder you will see:

enter image description here

and a parsed JSON response:

enter image description here

You could check if response is processed correctly in your adapter in:

xhr.addEventListener( 'load', () => {
    const response = xhr.response;
    ...
}

Listening to successful image upload may be tricky as there is no event directly related to it. Depending on what exactly you are trying to achieve you may try to extend you custom loader so when successful response is received (and resolve() called) you may execute some code. However, in this state the image element is still not updated (in model, view and DOM) with new URL and UploadAdapter lacks a direct access to editor instance so it may be hard to do anything complex.

Better way may be to listen to model changes, the similar way it is done in ImageUploadEditing plugin (see code here) checking the image uploadStatus attribute change:

editor.model.document.on( 'change', () => {
  const changes = doc.differ.getChanges();

  for ( const entry of changes ) {
    const uploaded = entry.type === 'attribute' && entry.attributeNewValue === 'complete' && entry.attributeOldValue === 'uploading';
    
    console.log( entry );
  }
} );

If it changes from uploading to complete it means the images was successfully uploaded:

enter image description here

You may also take a look at another answer, which shows how to hook into FileRepository API to track entire upload process - https://github.com/ckeditor/ckeditor5-image/issues/243#issuecomment-442393578.

like image 137
f1ames Avatar answered Oct 23 '22 05:10

f1ames