CKEditor 5 图片上传问题

CKEditor 5 Image Upload Issues

我正在我的项目中使用 ckeditor5。我必须支持图片上传,所以我搜索并关注了这个 Whosebug .

我创建了一个 uploadAdapter,它是:

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

现在解释一下。我有 2 个问题。

  1. 上传后(我在服务器上的上传工作正常并以 {default: url} 格式返回有效的 url,为什么我的图像内容作为 data-uri 插入而不是 url至于简单的图像演示 here。我希望我的图像像 url 一样。
  2. 我想听取一种成功的上传图像(带有从上传服务器调用中检索到的图像 ID)以在我的页面中插入一些内容。如何进行 ?

感谢您的帮助。

PS:我正在使用从 https://github.com/ckeditor/ckeditor5-build-classic

克隆的 git 仓库中的命令 'npm run build' 构建 ckeditor

编辑: 感谢接受的回复,我发现返回的数据是错误的。我没有在我的上传器前端返回任何 URL,这导致编辑器图像以 img-data 方式保留。返回有效的 URL 后,它会自动解析,我的编辑器图像包含有效的 url.

如果在成功上传后数据 uri 仍然被使用,我会假设服务器响应没有被正确处理并且接收到的 url 无法被检索。我已经测试了您提供的适配器代码并且它工作正常(在服务器端使用 CKFinder)。我会检查上传服务器响应的外观以及是否可以正确解析。

使用 CKFinder 时您会看到:

和解析的 JSON 响应:

您可以检查您的适配器是否正确处理了响应:

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

监听成功的图片上传可能比较棘手,因为没有直接相关的事件。根据您要实现的目标,您可以尝试扩展自定义加载程序,以便在收到成功响应(并调用 resolve() 时)您可以执行一些代码。然而,在这种状态下,图像元素仍然没有更新(在模型、视图和 DOM 中)新的 URL 和 UploadAdapter 缺乏对 editor 实例的直接访问,所以它可能很难做任何复杂的事情。

更好的方法可能是监听模型变化,与在 ImageUploadEditing 插件 (see code here) 中检查图像 uploadStatus 属性变化的方式类似:

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

如果由uploading变为complete则表示图片上传成功:

您还可以查看另一个答案,其中展示了如何挂接到 FileRepository API 以跟踪整个上传过程 - https://github.com/ckeditor/ckeditor5-image/issues/243#issuecomment-442393578.