如何在 CKEditor 5 中启用图片上传支持?
How to enable image upload support in CKEditor 5?
我将在我的项目中使用 ckeditor v5。我正在尝试使用图像插件,但找不到足够的相关信息。
如果您看到演示 here,您可以使用拖放轻松上传图像。但是当我尝试使用下载气球 zip 尝试拖放图像时,没有任何反应。也没有报错。
有没有办法在可下载版本中使用此图像支持?
是的,图片上传包含在所有可用的版本中。但是,为了使其工作,您需要配置一个现有的上传适配器或编写您自己的上传适配器。简而言之,上传适配器是一个简单的 class 其作用是将文件发送到服务器(以任何它想要的方式)并在完成后解析返回的承诺。
您可以在官方 Image upload 指南中阅读更多内容或查看下面可用选项的简短摘要。
官方上传适配器
有两个内置适配器:
对于 CKFinder,这需要您在服务器上安装 CKFinder 连接器。
在服务器上安装连接器后,您可以通过设置 config.ckfinder.uploadUrl
选项配置 CKEditor 将文件上传到该连接器:
ClassicEditor
.create( editorElement, {
ckfinder: {
uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json'
}
} )
.then( ... )
.catch( ... );
您还可以启用与 CKFinder 的客户端文件管理器的完全集成。查看 CKFinder integration demos and read more in the CKFinder integration 指南。
为Easy Image service which is a part of CKEditor Cloud Services.
您需要set up a Cloud Services account and once you created a token endpoint配置编辑器才能使用它:
ClassicEditor
.create( editorElement, {
cloudServices: {
tokenUrl: 'https://example.com/cs-token-endpoint',
uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/'
}
} )
.then( ... )
.catch( ... );
免责声明:这些是专有服务。
自定义上传适配器
您还可以编写自己的上传适配器,它将以您希望的方式将文件发送到您的服务器(或您喜欢发送文件的任何地方)。
请参阅 Custom image upload adapter 指南以了解如何实施它。
上传适配器的示例(即没有内置安全性)如下所示:
class MyUploadAdapter {
constructor( loader ) {
// CKEditor 5's FileLoader instance.
this.loader = loader;
// URL where to send files.
this.url = 'https://example.com/image/upload/path';
}
// Starts the upload process.
upload() {
return new Promise( ( resolve, reject ) => {
this._initRequest();
this._initListeners( resolve, reject );
this._sendRequest();
} );
}
// 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 ) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = 'Couldn\'t upload file:' + ` ${ loader.file.name }.`;
xhr.addEventListener( 'error', () => reject( genericErrorText ) );
xhr.addEventListener( 'abort', () => reject() );
xhr.addEventListener( 'load', () => {
const response = xhr.response;
if ( !response || response.error ) {
return reject( response && response.error ? response.error.message : genericErrorText );
}
// If the upload is successful, resolve the upload promise with an object containing
// at least the "default" URL, pointing to the image on the server.
resolve( {
default: response.url
} );
} );
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.
_sendRequest() {
const data = new FormData();
data.append( 'upload', this.loader.file );
this.xhr.send( data );
}
}
然后可以像这样启用:
function MyCustomUploadAdapterPlugin( editor ) {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
return new MyUploadAdapter( loader );
};
}
ClassicEditor
.create( document.querySelector( '#editor' ), {
extraPlugins: [ MyCustomUploadAdapterPlugin ],
// ...
} )
.catch( error => {
console.log( error );
} );
注意:以上只是一个上传适配器的例子。因此,它没有内置安全机制(例如 CSRF 保护)。
我正在搜索有关如何使用此控件的信息,发现官方文档很少。然而,经过多次试验和错误后,我确实让它工作了,所以我想我会分享。
最后,我将 CKEditor 5 简单上传适配器与 Angular 8 一起使用,效果很好。但是,您确实需要创建一个安装了上传适配器的自定义构建的 ckeditor。这很容易做到。我假设您已经拥有 ckeditor Angular 文件。
首先,创建一个新的angular 项目目录并将其命名为"cKEditor-Custom-Build" 或其他名称。不要 运行 ng new(Angular CLI),而是使用 npm 来获取要显示的编辑器的基础构建。对于这个例子,我使用的是 classic 编辑器。
https://github.com/ckeditor/ckeditor5-build-classic
转到 github 并将项目克隆或下载到新的闪亮构建目录中。
如果您使用的是 VS 代码,请打开目录并打开终端框并获取依赖项:
npm i
你现在已经有了基础构建,你需要安装一个上传适配器。 ckEditor 有一个。安装此包以获取简单的上传适配器:
npm install --save @ckeditor/ckeditor5-upload
..完成后打开项目中的 ckeditor.js 文件。它在 "src" 目录中。如果您一直在使用 ckEditor,那么它的内容应该看起来很熟悉。
将新的js文件导入到ckeditor.js文件中。该文件中将包含大量导入,并将其全部放在底部。
import SimpleUploadAdapter from '@ckeditor/ckeditor5-upload/src/adapters/simpleuploadadapter';
...接下来将导入添加到您的插件数组中。由于我使用的是 classic 编辑器,因此我的部分名为 "ClassicEditor.builtinPlugins",请将其添加到 TableToolbar 旁边。这就是所有配置。为此不需要额外的工具栏或配置。
构建你的 ckeditor-custom-build。
npm run build
Angular 的魔力将发挥作用,并在您的项目中创建一个 "build" 目录。它用于定制构建。
现在打开您的 angular 项目并为您的新构建创建一个目录。我实际上把我的放在 assets 子目录中,但它可以在任何你可以引用它的地方。
在 "src/assets" 中创建一个名为 "ngClassicEditor" 的目录,不管你叫什么,然后将构建文件复制到其中(你刚刚创建的)。接下来,在要使用编辑器的组件中,添加带有新构建路径的导入语句。
import * as Editor from '@app/../src/assets/ngClassicEditor/build/ckeditor.js';
快完成了...
最后一点是使用适配器应用于上传图像的 API 端点配置上传适配器。在您的组件 class 中创建一个配置。
public editorConfig = {
simpleUpload: {
// The URL that the images are uploaded to.
uploadUrl: environment.postSaveRteImage,
// Headers sent along with the XMLHttpRequest to the upload server.
headers: {
'X-CSRF-TOKEN': 'CSFR-Token',
Authorization: 'Bearer <JSON Web Token>'
}
}
};
我实际上在此处使用 environment transform,因为 URI 从开发更改为生产,但如果需要,您可以在其中硬编码直接 URL。
最后一部分是在模板中配置您的编辑器以使用您的新配置值。打开你component.html并修改你的ckeditor编辑器标签。
<ckeditor [editor]="Editor" id="editor" [config]="editorConfig">
</ckeditor>
就是这样。你完成了。测试,测试测试。
我的 API 是 .Net API,如果您需要一些示例代码,我很乐意与您分享。我真的希望这会有所帮助。
它对我很有用。感谢所有的回答。这是我的实现。
myUploadAdapter.ts
import { environment } from "./../../../environments/environment";
export class MyUploadAdapter {
public loader: any;
public url: string;
public xhr: XMLHttpRequest;
public token: string;
constructor(loader) {
this.loader = loader;
// change "environment.BASE_URL" key and API path
this.url = `${environment.BASE_URL}/api/v1/upload/attachments`;
// change "token" value with your token
this.token = localStorage.getItem("token");
}
upload() {
return new Promise(async (resolve, reject) => {
this.loader.file.then((file) => {
this._initRequest();
this._initListeners(resolve, reject, file);
this._sendRequest(file);
});
});
}
abort() {
if (this.xhr) {
this.xhr.abort();
}
}
_initRequest() {
const xhr = (this.xhr = new XMLHttpRequest());
xhr.open("POST", this.url, true);
// change "Authorization" header with your header
xhr.setRequestHeader("Authorization", this.token);
xhr.responseType = "json";
}
_initListeners(resolve, reject, file) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = "Couldn't upload file:" + ` ${file.name}.`;
xhr.addEventListener("error", () => reject(genericErrorText));
xhr.addEventListener("abort", () => reject());
xhr.addEventListener("load", () => {
const response = xhr.response;
if (!response || response.error) {
return reject(
response && response.error ? response.error.message : genericErrorText
);
}
// change "response.data.fullPaths[0]" with image URL
resolve({
default: response.data.fullPaths[0],
});
});
if (xhr.upload) {
xhr.upload.addEventListener("progress", (evt) => {
if (evt.lengthComputable) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
});
}
}
_sendRequest(file) {
const data = new FormData();
// change "attachments" key
data.append("attachments", file);
this.xhr.send(data);
}
}
component.html
<ckeditor
(ready)="onReady($event)"
[editor]="editor"
[(ngModel)]="html"
></ckeditor>
component.ts
import { MyUploadAdapter } from "./myUploadAdapter";
import { Component, OnInit } from "@angular/core";
import * as DecoupledEditor from "@ckeditor/ckeditor5-build-decoupled-document";
@Component({
selector: "xxx",
templateUrl: "xxx.html",
})
export class XXX implements OnInit {
public editor: DecoupledEditor;
public html: string;
constructor() {
this.editor = DecoupledEditor;
this.html = "";
}
public onReady(editor) {
editor.plugins.get("FileRepository").createUploadAdapter = (loader) => {
return new MyUploadAdapter(loader);
};
editor.ui
.getEditableElement()
.parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
}
public ngOnInit() {}
}
在 React 中
使用 MyCustomUploadAdapterPlugin 创建一个新文件
import Fetch from './Fetch'; //my common fetch function
class MyUploadAdapter {
constructor( loader ) {
// The file loader instance to use during the upload.
this.loader = loader;
}
// Starts the upload process.
upload() {
return this.loader.file
.then( file => new Promise( ( resolve, reject ) => {
const toBase64 = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
return toBase64(file).then(cFile=>{
return Fetch("admin/uploadimage", {
imageBinary: cFile
}).then((d) => {
if (d.status) {
this.loader.uploaded = true;
resolve( {
default: d.response.url
} );
} else {
reject(`Couldn't upload file: ${ file.name }.`)
}
});
})
} ) );
}
}
// ...
export default function MyCustomUploadAdapterPlugin( editor ) {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
// Configure the URL to the upload script in your back-end here!
return new MyUploadAdapter( loader );
};
}
并在
import MyCustomUploadAdapterPlugin from '../common/ckImageUploader';
import CKEditor from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
<CKEditor
editor={ClassicEditor}
data={quesText}
placeholder="Question Text"
config={{extraPlugins:[MyCustomUploadAdapterPlugin]}} //use
/>
我使用了这个配置:
public editorConfig = {
simpleUpload: {
uploadUrl: environment.postSaveRteImage,
headers: {
'X-CSRF-TOKEN': 'CSFR-Token',
Authorization: 'Bearer <JSON Web Token>'
}
}
图片上传成功,响应为{"url": "image-url"}。
但在前端 ckeditor 的警报中说
Cannot upload file: undefined.
对于遇到 XHR 问题的人,您也可以使用 fetch api,这似乎工作正常
constructor(loader) {
// The file loader instance to use during the upload.
this.loader = loader;
this.url = '/upload';
}
request(file) {
return fetch(this.url, { // Your POST endpoint
method: 'POST',
headers: {
'x-csrf-token': _token
},
body: file // This is your file object
});
}
upload() {
const formData = new FormData();
this.loader.file.then((filenew) => {
console.log(filenew);
formData.append('file', filenew, filenew.name);
return new Promise((resolve, reject) => {
this.request(formData).then(
response => response.json() // if the response is a JSON object
).then(
success => console.log(success) // Handle the success response object
).catch(
error => console.log(error) // Handle the error response object
);
})
});
}
我将在我的项目中使用 ckeditor v5。我正在尝试使用图像插件,但找不到足够的相关信息。
如果您看到演示 here,您可以使用拖放轻松上传图像。但是当我尝试使用下载气球 zip 尝试拖放图像时,没有任何反应。也没有报错。
有没有办法在可下载版本中使用此图像支持?
是的,图片上传包含在所有可用的版本中。但是,为了使其工作,您需要配置一个现有的上传适配器或编写您自己的上传适配器。简而言之,上传适配器是一个简单的 class 其作用是将文件发送到服务器(以任何它想要的方式)并在完成后解析返回的承诺。
您可以在官方 Image upload 指南中阅读更多内容或查看下面可用选项的简短摘要。
官方上传适配器
有两个内置适配器:
对于 CKFinder,这需要您在服务器上安装 CKFinder 连接器。
在服务器上安装连接器后,您可以通过设置
config.ckfinder.uploadUrl
选项配置 CKEditor 将文件上传到该连接器:ClassicEditor .create( editorElement, { ckfinder: { uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json' } } ) .then( ... ) .catch( ... );
您还可以启用与 CKFinder 的客户端文件管理器的完全集成。查看 CKFinder integration demos and read more in the CKFinder integration 指南。
为Easy Image service which is a part of CKEditor Cloud Services.
您需要set up a Cloud Services account and once you created a token endpoint配置编辑器才能使用它:
ClassicEditor .create( editorElement, { cloudServices: { tokenUrl: 'https://example.com/cs-token-endpoint', uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/' } } ) .then( ... ) .catch( ... );
免责声明:这些是专有服务。
自定义上传适配器
您还可以编写自己的上传适配器,它将以您希望的方式将文件发送到您的服务器(或您喜欢发送文件的任何地方)。
请参阅 Custom image upload adapter 指南以了解如何实施它。
上传适配器的示例(即没有内置安全性)如下所示:
class MyUploadAdapter {
constructor( loader ) {
// CKEditor 5's FileLoader instance.
this.loader = loader;
// URL where to send files.
this.url = 'https://example.com/image/upload/path';
}
// Starts the upload process.
upload() {
return new Promise( ( resolve, reject ) => {
this._initRequest();
this._initListeners( resolve, reject );
this._sendRequest();
} );
}
// 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 ) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = 'Couldn\'t upload file:' + ` ${ loader.file.name }.`;
xhr.addEventListener( 'error', () => reject( genericErrorText ) );
xhr.addEventListener( 'abort', () => reject() );
xhr.addEventListener( 'load', () => {
const response = xhr.response;
if ( !response || response.error ) {
return reject( response && response.error ? response.error.message : genericErrorText );
}
// If the upload is successful, resolve the upload promise with an object containing
// at least the "default" URL, pointing to the image on the server.
resolve( {
default: response.url
} );
} );
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.
_sendRequest() {
const data = new FormData();
data.append( 'upload', this.loader.file );
this.xhr.send( data );
}
}
然后可以像这样启用:
function MyCustomUploadAdapterPlugin( editor ) {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
return new MyUploadAdapter( loader );
};
}
ClassicEditor
.create( document.querySelector( '#editor' ), {
extraPlugins: [ MyCustomUploadAdapterPlugin ],
// ...
} )
.catch( error => {
console.log( error );
} );
注意:以上只是一个上传适配器的例子。因此,它没有内置安全机制(例如 CSRF 保护)。
我正在搜索有关如何使用此控件的信息,发现官方文档很少。然而,经过多次试验和错误后,我确实让它工作了,所以我想我会分享。
最后,我将 CKEditor 5 简单上传适配器与 Angular 8 一起使用,效果很好。但是,您确实需要创建一个安装了上传适配器的自定义构建的 ckeditor。这很容易做到。我假设您已经拥有 ckeditor Angular 文件。
首先,创建一个新的angular 项目目录并将其命名为"cKEditor-Custom-Build" 或其他名称。不要 运行 ng new(Angular CLI),而是使用 npm 来获取要显示的编辑器的基础构建。对于这个例子,我使用的是 classic 编辑器。
https://github.com/ckeditor/ckeditor5-build-classic
转到 github 并将项目克隆或下载到新的闪亮构建目录中。
如果您使用的是 VS 代码,请打开目录并打开终端框并获取依赖项:
npm i
你现在已经有了基础构建,你需要安装一个上传适配器。 ckEditor 有一个。安装此包以获取简单的上传适配器:
npm install --save @ckeditor/ckeditor5-upload
..完成后打开项目中的 ckeditor.js 文件。它在 "src" 目录中。如果您一直在使用 ckEditor,那么它的内容应该看起来很熟悉。
将新的js文件导入到ckeditor.js文件中。该文件中将包含大量导入,并将其全部放在底部。
import SimpleUploadAdapter from '@ckeditor/ckeditor5-upload/src/adapters/simpleuploadadapter';
...接下来将导入添加到您的插件数组中。由于我使用的是 classic 编辑器,因此我的部分名为 "ClassicEditor.builtinPlugins",请将其添加到 TableToolbar 旁边。这就是所有配置。为此不需要额外的工具栏或配置。
构建你的 ckeditor-custom-build。
npm run build
Angular 的魔力将发挥作用,并在您的项目中创建一个 "build" 目录。它用于定制构建。
现在打开您的 angular 项目并为您的新构建创建一个目录。我实际上把我的放在 assets 子目录中,但它可以在任何你可以引用它的地方。
在 "src/assets" 中创建一个名为 "ngClassicEditor" 的目录,不管你叫什么,然后将构建文件复制到其中(你刚刚创建的)。接下来,在要使用编辑器的组件中,添加带有新构建路径的导入语句。
import * as Editor from '@app/../src/assets/ngClassicEditor/build/ckeditor.js';
快完成了...
最后一点是使用适配器应用于上传图像的 API 端点配置上传适配器。在您的组件 class 中创建一个配置。
public editorConfig = {
simpleUpload: {
// The URL that the images are uploaded to.
uploadUrl: environment.postSaveRteImage,
// Headers sent along with the XMLHttpRequest to the upload server.
headers: {
'X-CSRF-TOKEN': 'CSFR-Token',
Authorization: 'Bearer <JSON Web Token>'
}
}
};
我实际上在此处使用 environment transform,因为 URI 从开发更改为生产,但如果需要,您可以在其中硬编码直接 URL。
最后一部分是在模板中配置您的编辑器以使用您的新配置值。打开你component.html并修改你的ckeditor编辑器标签。
<ckeditor [editor]="Editor" id="editor" [config]="editorConfig">
</ckeditor>
就是这样。你完成了。测试,测试测试。
我的 API 是 .Net API,如果您需要一些示例代码,我很乐意与您分享。我真的希望这会有所帮助。
它对我很有用。感谢所有的回答。这是我的实现。
myUploadAdapter.ts
import { environment } from "./../../../environments/environment";
export class MyUploadAdapter {
public loader: any;
public url: string;
public xhr: XMLHttpRequest;
public token: string;
constructor(loader) {
this.loader = loader;
// change "environment.BASE_URL" key and API path
this.url = `${environment.BASE_URL}/api/v1/upload/attachments`;
// change "token" value with your token
this.token = localStorage.getItem("token");
}
upload() {
return new Promise(async (resolve, reject) => {
this.loader.file.then((file) => {
this._initRequest();
this._initListeners(resolve, reject, file);
this._sendRequest(file);
});
});
}
abort() {
if (this.xhr) {
this.xhr.abort();
}
}
_initRequest() {
const xhr = (this.xhr = new XMLHttpRequest());
xhr.open("POST", this.url, true);
// change "Authorization" header with your header
xhr.setRequestHeader("Authorization", this.token);
xhr.responseType = "json";
}
_initListeners(resolve, reject, file) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = "Couldn't upload file:" + ` ${file.name}.`;
xhr.addEventListener("error", () => reject(genericErrorText));
xhr.addEventListener("abort", () => reject());
xhr.addEventListener("load", () => {
const response = xhr.response;
if (!response || response.error) {
return reject(
response && response.error ? response.error.message : genericErrorText
);
}
// change "response.data.fullPaths[0]" with image URL
resolve({
default: response.data.fullPaths[0],
});
});
if (xhr.upload) {
xhr.upload.addEventListener("progress", (evt) => {
if (evt.lengthComputable) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
});
}
}
_sendRequest(file) {
const data = new FormData();
// change "attachments" key
data.append("attachments", file);
this.xhr.send(data);
}
}
component.html
<ckeditor
(ready)="onReady($event)"
[editor]="editor"
[(ngModel)]="html"
></ckeditor>
component.ts
import { MyUploadAdapter } from "./myUploadAdapter";
import { Component, OnInit } from "@angular/core";
import * as DecoupledEditor from "@ckeditor/ckeditor5-build-decoupled-document";
@Component({
selector: "xxx",
templateUrl: "xxx.html",
})
export class XXX implements OnInit {
public editor: DecoupledEditor;
public html: string;
constructor() {
this.editor = DecoupledEditor;
this.html = "";
}
public onReady(editor) {
editor.plugins.get("FileRepository").createUploadAdapter = (loader) => {
return new MyUploadAdapter(loader);
};
editor.ui
.getEditableElement()
.parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
}
public ngOnInit() {}
}
在 React 中
使用 MyCustomUploadAdapterPlugin 创建一个新文件
import Fetch from './Fetch'; //my common fetch function
class MyUploadAdapter {
constructor( loader ) {
// The file loader instance to use during the upload.
this.loader = loader;
}
// Starts the upload process.
upload() {
return this.loader.file
.then( file => new Promise( ( resolve, reject ) => {
const toBase64 = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
return toBase64(file).then(cFile=>{
return Fetch("admin/uploadimage", {
imageBinary: cFile
}).then((d) => {
if (d.status) {
this.loader.uploaded = true;
resolve( {
default: d.response.url
} );
} else {
reject(`Couldn't upload file: ${ file.name }.`)
}
});
})
} ) );
}
}
// ...
export default function MyCustomUploadAdapterPlugin( editor ) {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
// Configure the URL to the upload script in your back-end here!
return new MyUploadAdapter( loader );
};
}
并在
import MyCustomUploadAdapterPlugin from '../common/ckImageUploader';
import CKEditor from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
<CKEditor
editor={ClassicEditor}
data={quesText}
placeholder="Question Text"
config={{extraPlugins:[MyCustomUploadAdapterPlugin]}} //use
/>
我使用了这个配置:
public editorConfig = {
simpleUpload: {
uploadUrl: environment.postSaveRteImage,
headers: {
'X-CSRF-TOKEN': 'CSFR-Token',
Authorization: 'Bearer <JSON Web Token>'
}
}
图片上传成功,响应为{"url": "image-url"}。 但在前端 ckeditor 的警报中说
Cannot upload file: undefined.
对于遇到 XHR 问题的人,您也可以使用 fetch api,这似乎工作正常
constructor(loader) {
// The file loader instance to use during the upload.
this.loader = loader;
this.url = '/upload';
}
request(file) {
return fetch(this.url, { // Your POST endpoint
method: 'POST',
headers: {
'x-csrf-token': _token
},
body: file // This is your file object
});
}
upload() {
const formData = new FormData();
this.loader.file.then((filenew) => {
console.log(filenew);
formData.append('file', filenew, filenew.name);
return new Promise((resolve, reject) => {
this.request(formData).then(
response => response.json() // if the response is a JSON object
).then(
success => console.log(success) // Handle the success response object
).catch(
error => console.log(error) // Handle the error response object
);
})
});
}