Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Nelex/3b1a83e8b60a74dc4a90022ca27a8b75 to your computer and use it in GitHub Desktop.
Save Nelex/3b1a83e8b60a74dc4a90022ca27a8b75 to your computer and use it in GitHub Desktop.

Revisions

  1. Nelex revised this gist Sep 8, 2020. 1 changed file with 11 additions and 6 deletions.
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@
    Сразу обозначу что код рабочий, но не чистый и добавлял его чтобы не забыть что как делал, но и возможно кому-то пригодиться. Кому нужно, код поправят под то как им нужно. Все это черновой код и продакшн код я не публикую специально.
    В итоге код выглядит так:

    <script>
    ```javascript
    class MyUploadAdapter {
    constructor( loader, url, t ) {
    // CKEditor 5's FileLoader instance.
    @@ -132,11 +132,11 @@
    }
    });

    </script>
    ```
    Бекенд на ларавеле отрабатывает приблизительно так:
    <?php namespace App\Http\Controllers\Front;
    ```php
    <?php namespace App\Http\Controllers\Front;

    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
    @@ -164,16 +164,21 @@ class Fileuploader extends Controller {

    }

    ```

    Не забудьте путь добавить в исключение VerifyCsrfToken для Laravel или прикрутить нормально проверку:
    ```php
    protected $except = [
    'uploader',
    ];

    ```

    и сам путь добавить в роутинг:
    ```php
    Route::group(['prefix' => 'uploader', 'nocsrf' => true], function () {
    Route::match(['get', 'post'], '/', 'Fileuploader@upload')->name('front_uploader');
    });
    ```
    Протестированно на внутренних проектах https://100.ks.ua и отработало нормально

  2. Nelex created this gist Sep 8, 2020.
    179 changes: 179 additions & 0 deletions CKEditor 5 simpleUpload для загрузки картинок.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,179 @@
    Так получилось что прикрутить один визивиг недостаточно, нужна по-любому загрузка картинок. Визуально лучшим редактором и более подходящим по возможностям мы выбрали CKEditor 5 в режиме balloon block.
    Чтобы было понятнее, режим balloon block это блочное редактирование прямо на странице с материалом.

    Но есть проблема, конфиг прошлой версии CKEditor 4 не подходит. Вторая проблема, конфиг MyCustomUploadAdapter, который достаточно просто найти в сети, не работает. Перепробовал несколько версий, то идут версии чисто под реакт, то нерабочая, отправляющая вместо файла на сервер Promise.

    В итоге, использовал тот же MyCustomUploadAdapter из сети с поправой из свежей версии CKFinder адаптера.

    Сразу обозначу что код рабочий, но не чистый и добавлял его чтобы не забыть что как делал, но и возможно кому-то пригодиться. Кому нужно, код поправят под то как им нужно. Все это черновой код и продакшн код я не публикую специально.
    В итоге код выглядит так:

    <script>
    class MyUploadAdapter {
    constructor( loader, url, t ) {
    // CKEditor 5's FileLoader instance.
    this.loader = loader;

    // URL where to send files.
    this.url = '{{route('front_uploader')}}';
    //translate function
    //this.t = t;
    }


    // Starts the upload process.
    upload() {
    return this.loader.file.then( file => {
    return new Promise( ( resolve, reject ) => {
    this._initRequest();
    this._initListeners( resolve, reject, file );
    this._sendRequest( file );
    } );
    } );
    }

    // Aborts the upload process.
    abort() {
    if ( this.xhr ) {
    this.xhr.abort();
    }
    }

    // Example implementation using XMLHttpRequest.
    _initRequest() {
    const xhr = this.xhr = new XMLHttpRequest();

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

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

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

    if ( !response || !response.uploaded ) {
    console.log(response);
    return reject( response && response.error && response.error.message ? response.error.message : genericError );
    }

    resolve( {
    default: response.url
    } );
    } );

    // Upload progress when it's supported.
    /* istanbul ignore else */
    if ( xhr.upload ) {
    xhr.upload.addEventListener( 'progress', evt => {
    if ( evt.lengthComputable ) {
    loader.uploadTotal = evt.total;
    loader.uploaded = evt.loaded;
    }
    } );
    }
    }

    /**
    * Prepares the data and sends the request.
    *
    * @private
    * @param {File} file File instance to be uploaded.
    */
    _sendRequest( file ) {
    // Prepare form data.
    const data = new FormData();
    data.append( 'upload', file );
    //data.append( 'ckCsrfToken', getCsrfToken() ); //это для тех кому важна csrf от CKEditor/CKFinder

    // Send request.
    this.xhr.send( data );
    }
    }

    document.addEventListener('DOMContentLoaded',function (){

    function MyCustomUploadAdapterPlugin( editor ) {
    editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
    return new MyUploadAdapter( loader );
    };
    }

    const config = {

    extraPlugins: [ MyCustomUploadAdapterPlugin ],
    simpleUpload: {
    uploadUrl: '/uploader' //путь куда сохраняется материал
    }
    };
    var ta = document.querySelector( '.textarea' );

    BalloonEditor
    .create( ta, config
    ).then( editor => { window.editor = editor } )
    .catch( error => {
    console.error( error );
    } );

    //код сохранения по клику на кнопку
    document.getElementById( 'saveArticle' ).onclick = () => {
    $.post('{{route('admin_articles_edit',['id'=>$record->id])}}',{ //роут сохранения статьи
    'fields[body]':editor.getData(),
    _token: '{{ csrf_token() }}' //csrf от Laravel
    })
    }
    });

    </script>
    Бекенд на ларавеле отрабатывает приблизительно так:
    <?php namespace App\Http\Controllers\Front;

    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\File;
    use Illuminate\Support\Facades\Storage;

    class Fileuploader extends Controller {

    public function upload(Request $request){
    if (Auth::guest()) abort(403);
    $file = $request->file('upload');
    if ($file->isReadable()){
    $filename = md5(date("YmdHis").rand(5,50));
    $extension = $file->getClientOriginalExtension();
    Storage::disk('front_uploaded')->put($filename.'.'.$extension, File::get($file));
    $http_path = '/images/uploaded/front/'.$filename.".".$extension;
    return ['url'=>$http_path,'file'=>['name'=>$filename,'url'=>$http_path],'uploaded'=>true];
    }
    else
    {
    return ['failed'];
    }
    }

    }

    Не забудьте путь добавить в исключение VerifyCsrfToken для Laravel или прикрутить нормально проверку:
    protected $except = [
    'uploader',
    ];

    и сам путь добавить в роутинг:
    Route::group(['prefix' => 'uploader', 'nocsrf' => true], function () {
    Route::match(['get', 'post'], '/', 'Fileuploader@upload')->name('front_uploader');
    });


    Протестированно на внутренних проектах https://100.ks.ua и отработало нормально