如何接收上传图片的 URL 并将其传递给 CK Editor 中的 "src" 属性?
How to receive the URL of uploaded image and pass it to "src" attribute in CK Editor?
和Base64 image upload adapter一样,CKEditor对图片进行明显的编码,转为Base64格式,然后插入结果为<img src="data:image/png;base64, code... >
。代码可能很长;我想要上传的图片 URL。
在我的应用程序中,我需要以下功能:
- 将图像转换为 Base64。我基本上知道怎么做:
async function encodeSingleFileTo64base(targetFile: File): Promise<string> {
const fileReader: FileReader = new FileReader();
fileReader.readAsDataURL(targetFile);
return new Promise<string>((resolve: (encodedFile: string) => void, reject: (error: Error) => void): void => {
fileReader.onload = (filedHasBeenReadEvent: ProgressEvent<FileReader>): void => {
if (filedHasBeenReadEvent.target === null || filedHasBeenReadEvent.target.result === null) {
reject(new Error("Failed to encode the image file."));
return;
}
resolve(String(filedHasBeenReadEvent.target.result));
};
});
}
- 通过 GraphQL 提交 Base64 代码。我基本可以:
import AWSAmplifyAPI, { graphqlOperation, GraphQLResult } from "@aws-amplify/api";
async function uploadPhotoAndGetURL(photoBase64: string): Promise<string> {
return (await AWSAmplifyAPI.graphql(graphqlOperation(
`mutation($photoBase64: String!) { uploadPhoto(photoBase64: $photoBase64) }`,
{ photoBase64 }
))).uploadPhoto;
}
- 让 CK 编辑器将收到的响应 URL 添加到
src=""
(这是当前问题的主题)。
这是来自 documentation 的解决方案模板:
class MyUploadAdapter {
constructor( loader ) {
this.loader = loader;
}
upload() {
return loader.file
.then( file => server.upload( file ) );
}
abort() {
server.abortUpload();
}
}
第一个问题:如何在 upload() 方法中链接两个异步函数?
编码和数据提交都是异步操作。
我一直很困惑如何与 loader.file.then()
.
兼容
第二个问题:如何将收到的URL传递给CK编辑器?
我无法从建议的解决方案模板中理解我们如何接收上传的图像 URL 并将其传递给 src
属性。
First problem: how to chain two async functions in upload() method?
从这里开始:https://thoughtbot.com/blog/chaining-events-like-a-boss
示例:
const timeUserRequest = async () => {
const before = await getCurrentTimeAsync()
await getUserDataViaHttp()
const after = await getCurrentTimeAsync()
return (after - before)
};
Second problem: how to pass recieved URL to CK editor?
您是如何提出请求的?你看到这个例子了吗?
class MyUploadAdapter {
// ...
// Initializes XMLHttpRequest listeners.
_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;
// This example assumes the XHR server's "response" object will come with
// an "error" which has its own "message" that can be passed to reject()
// in the upload promise.
//
// Your integration may handle upload errors in a different way so make sure
// it is done properly. The reject() function must be called when the upload fails.
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.
// This URL will be used to display the image in the content. Learn more in the
// UploadAdapter#upload documentation.
resolve( {
default: response.url
} );
} );
// Upload progress when it is supported. The file loader has the #uploadTotal and #uploaded
// properties which are used e.g. to display the upload progress bar in the editor
// user interface.
if ( xhr.upload ) {
xhr.upload.addEventListener( 'progress', evt => {
if ( evt.lengthComputable ) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
} );
}
}
}
和Base64 image upload adapter一样,CKEditor对图片进行明显的编码,转为Base64格式,然后插入结果为<img src="data:image/png;base64, code... >
。代码可能很长;我想要上传的图片 URL。
在我的应用程序中,我需要以下功能:
- 将图像转换为 Base64。我基本上知道怎么做:
async function encodeSingleFileTo64base(targetFile: File): Promise<string> {
const fileReader: FileReader = new FileReader();
fileReader.readAsDataURL(targetFile);
return new Promise<string>((resolve: (encodedFile: string) => void, reject: (error: Error) => void): void => {
fileReader.onload = (filedHasBeenReadEvent: ProgressEvent<FileReader>): void => {
if (filedHasBeenReadEvent.target === null || filedHasBeenReadEvent.target.result === null) {
reject(new Error("Failed to encode the image file."));
return;
}
resolve(String(filedHasBeenReadEvent.target.result));
};
});
}
- 通过 GraphQL 提交 Base64 代码。我基本可以:
import AWSAmplifyAPI, { graphqlOperation, GraphQLResult } from "@aws-amplify/api";
async function uploadPhotoAndGetURL(photoBase64: string): Promise<string> {
return (await AWSAmplifyAPI.graphql(graphqlOperation(
`mutation($photoBase64: String!) { uploadPhoto(photoBase64: $photoBase64) }`,
{ photoBase64 }
))).uploadPhoto;
}
- 让 CK 编辑器将收到的响应 URL 添加到
src=""
(这是当前问题的主题)。
这是来自 documentation 的解决方案模板:
class MyUploadAdapter {
constructor( loader ) {
this.loader = loader;
}
upload() {
return loader.file
.then( file => server.upload( file ) );
}
abort() {
server.abortUpload();
}
}
第一个问题:如何在 upload() 方法中链接两个异步函数?
编码和数据提交都是异步操作。
我一直很困惑如何与 loader.file.then()
.
第二个问题:如何将收到的URL传递给CK编辑器?
我无法从建议的解决方案模板中理解我们如何接收上传的图像 URL 并将其传递给 src
属性。
First problem: how to chain two async functions in upload() method?
从这里开始:https://thoughtbot.com/blog/chaining-events-like-a-boss
示例:
const timeUserRequest = async () => {
const before = await getCurrentTimeAsync()
await getUserDataViaHttp()
const after = await getCurrentTimeAsync()
return (after - before)
};
Second problem: how to pass recieved URL to CK editor?
您是如何提出请求的?你看到这个例子了吗?
class MyUploadAdapter {
// ...
// Initializes XMLHttpRequest listeners.
_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;
// This example assumes the XHR server's "response" object will come with
// an "error" which has its own "message" that can be passed to reject()
// in the upload promise.
//
// Your integration may handle upload errors in a different way so make sure
// it is done properly. The reject() function must be called when the upload fails.
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.
// This URL will be used to display the image in the content. Learn more in the
// UploadAdapter#upload documentation.
resolve( {
default: response.url
} );
} );
// Upload progress when it is supported. The file loader has the #uploadTotal and #uploaded
// properties which are used e.g. to display the upload progress bar in the editor
// user interface.
if ( xhr.upload ) {
xhr.upload.addEventListener( 'progress', evt => {
if ( evt.lengthComputable ) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
} );
}
}
}