Адаптер загрузки CKEditor отправляет [object Promise] на сервер

Я пытался внедрить CKEditor5 в проект vuejs, и после того, как вся инфраструктура заработала, я не могу загрузить фактический файл на сервер php. Код вызывает сервер, и если я возвращаю сообщение об успешном завершении и URL-адрес файла, все работает правильно. Вот мой код:

    <template> 
        ...
        <ckeditor :editor = "editor" v-model = "details.SystemText" :config = "editorConfig"></ckeditor>
        ...
    </template>


    import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
    class UploadAdapter {
        constructor(loader) {
            this.loader = loader;
        }

        upload() {
            return new Promise((resolve, reject) => {
                const data = new FormData();
                data.append('upload', this.loader.file);

                axios({
                    url: '/index/uploadimage',
                    method: 'post',
                    data,
                    headers: {
                        'Content-Type': 'multipart/form-data;'
                    },
                    withCredentials: false
                }).then(response => {
                    if (response.data.result == 'success') {
                        resolve({
                            default: response.data.url
                        });
                    } else {
                        reject(response.data.message);
                    }
                }).catch(response => {
                    reject ( 'Upload failed');
                });

            });
        }

        abort() {
        }
    }
    export default {
        data () {
                details: {},
                editor: ClassicEditor,
                editorConfig: {
                    extraPlugins: [ this.MyCustomUploadAdapterPlugin ],
                }
        },
        methods: {
            MyCustomUploadAdapterPlugin ( editor ) {
                editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {

                    return new UploadAdapter( loader );
                };
            },
        }

Щелчок по значку изображения на панели инструментов правильно отобразит диалоговое окно выбора файла, а после выбора файла сообщение будет отправлено на сервер. Однако бинарный файл не отправляется, а просто:

Form Data

------WebKitFormBoundaryqPGA20WRKz9VvADd
Content-Disposition: form-data; name = "upload"

[object Promise]

Я провел два дня, просматривая все другие плагины, такие как CKFinder и другие, и, кажется, я всегда получаю один и тот же контент, отправляемый на сервер. Линия

data.append('upload', this.loader.file);

похоже, не добавляется фактический файл, что, я думаю, он должен делать.

Моя ценность this.loader

loader.file
Promise {<pending>}
__proto__: Promise
catch: ƒ catch()
constructor: ƒ Promise()
finally: ƒ finally()
then: ƒ then()
Symbol(Symbol.toStringTag): "Promise"
__proto__: Object
[[PromiseStatus]]: "pending"
[[PromiseValue]]: undefined

Пытался использовать их облачный сервис, но указал на свои собственные URL-адреса, и это заработало для загрузки.

                editorConfig: {
                    cloudServices: {
                        tokenUrl: '/index/tokenendpoint',
                        uploadUrl: '/index/uploadimage'
                    }
                }

Я также смог удалить весь код адаптера загрузки.

Спасибо

Я просматривал их облачный сервис, чтобы убедиться, что он отправляет правильно, и это было так. Я просто изменил URL-адреса облачного сервера на свои собственные, и это сработало. Я опубликовал изменения в своем вопросе. Не очень понял, почему у меня не работает loader.file, но в итоге файл загрузился.

Bob 12.03.2019 00:08

Кажется, что гид об адаптерах загрузки имеет некоторую ошибку. Простите за это. Готово: github.com/ckeditor/ckeditor5/issues/1618.

Reinmar 13.03.2019 13:22

Документация была обновлена, и новая версия скоро будет опубликована на ckeditor.com/docs.

oleq 13.03.2019 17:26
Применение градиента к изображению с помощью CSS
Применение градиента к изображению с помощью CSS
Здравствуйте, братья и сестры, как дела? Недавно я застрял на применении градиента к изображению. Я применял это много раз, но иногда наши требования...
Получение URL-адреса изображения курса в Moodle с помощью PHP
Получение URL-адреса изображения курса в Moodle с помощью PHP
Moodle - это популярная система управления обучением с открытым исходным кодом, используемая многими учебными заведениями и организациями по всему...
3
3
2 403
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Используйте JQuery Ajax. Я не могу найти эквивалент с помощью fetch или axios. Ключом является установка contentType: false и processData: false.

upload() {
        return new Promise((resolve, reject) => {
            const data = new FormData();
            data.append('postedFile', this.loader.file);
            $.ajax({
                url: '/index/uploadimage',
                data,
                contentType: false,
                processData: false,
                type: 'POST',
                success: response => {
                    resolve({
                        default: response.data.url
                    });
                },
                error: () => {
                    reject('Upload failed');
                }
            });
        });
    }

Используя VueJS, я избегаю использования JQuery. Рассматривал SummerNote вместо CKEditor, но для этого требовался JQuery. Установил JQuery только для того, чтобы посмотреть, работает ли их компонент ajax, но свойство «postefFile», отправленное на сервер, по-прежнему «[object Promise]».

Bob 11.03.2019 22:53

Они работают над этим, это ошибка. https://github.com/ckeditor/ckeditor5/issues/1618

Ответ принят как подходящий

Причина вашей проблемы в том, что в версии 11.0.0 плагина ckeditor5-upload был изменен API, loader.file теперь Promise (см. примечания к выпуску). К сожалению, документы не были обновлены соответствующим образом.

Вам нужно немного настроить функцию загрузки:

upload() {
    return this.loader.file
        .then( uploadedFile => {
            return new Promise( ( resolve, reject ) => {
            const data = new FormData();
            data.append( 'upload', uploadedFile );

            axios( {
                url: '/index/uploadimage',
                method: 'post',
                data,
                headers: {
                    'Content-Type': 'multipart/form-data;'
                },
                withCredentials: false
            } ).then( response => {
                if ( response.data.result == 'success' ) {
                    resolve( {
                        default: response.data.url
                    } );
                } else {
                    reject( response.data.message );
                }
            } ).catch( response => {
                reject( 'Upload failed' );
            } );

        } );
    } );
}

документы, в которых была эта проблема теперь исправлен и правильно использует промис. Надеюсь, это решит проблему для вас!

Я заменил свой код этим, и загрузка была двоичным файлом. Отлично... однако с моим кодом должна быть какая-то другая проблема, заключающаяся в том, что изображение появляется, а затем сразу же исчезает. Я скопировал точный пример кода адаптера из Документов, заменив их URL своим, и это сработало. Я хотел бы знать, почему изображение было стерто сразу после загрузки, могло ли это иметь какое-то отношение к слушателю для прогресса и т. д. Опубликую, если почувствую необходимость в дальнейшем расследовании, но после времени, которое я потратил на это, я просто хочу двигаться дальше.

Bob 14.03.2019 14:30

У меня нет возможности попробовать какой-либо код сейчас, но я предполагаю, что вы не возвращаете свойство url в ответе. Ответ AFAIR должен содержать URL-адрес с... ну, URL-адрес файла после его загрузки (потому что его также можно было бы переименовать, чтобы избежать конфликтов). Это помогает?

Marek Lewandowski 15.03.2019 17:19

Другие вопросы по теме