CKEditor 5最簡單的做法就是去Online Builder點一點,把你要的模組點完之後,按照sample裡面的範例放進你的網頁。但這次我有放圖片的需求,搞了半天才找到可行的做法。記得在Online Builder加進Image Upload及Simple Upload Adapter。
在加入CKEditor的語法前面加上下面程式碼
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 ) => {
this._initRequest();
this._initListeners( resolve, reject, file );
this._sendRequest( file );
} ) );
}
// Aborts the upload process.
abort() {
if ( this.xhr ) {
this.xhr.abort();
}
}
// Initializes the XMLHttpRequest object using the URL passed to the constructor.
_initRequest() {
const xhr = this.xhr = new XMLHttpRequest();
// Note that your request may look different. It is up to you and your editor
// integration to choose the right communication channel. This example uses
// a POST request with JSON as a data structure but your configuration
// could be different.
xhr.open( 'POST', 'YOUR_UPLOAD_URL', true );
xhr.responseType = 'json';
}
// 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;
}
} );
}
}
// Prepares the data and sends the request.
_sendRequest( file ) {
// Prepare the form data.
const data = new FormData();
data.append( 'upload', file );
// Important note: This is the right place to implement security mechanisms
// like authentication and CSRF protection. For instance, you can use
// XMLHttpRequest.setRequestHeader() to set the request headers containing
// the CSRF token generated earlier by your application.
// Send the request.
this.xhr.send( data );
}
}
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 );
};
}
把其中 YOUR_UPLOAD_URL
修改為後端接收圖片的網址。CKEditor原本只要用
ClassicEditor.create( document.querySelector( 'YOUR_QUERY' ),{});
把他修改成
ClassicEditor.create( document.querySelector( 'YOUR_QUERY'), {
extraPlugins: [ MyCustomUploadAdapterPlugin ],
});
後端PHP程式碼
<?php
// Upload script for CKEditor.
// Use at your own risk, no warranty provided. Be careful about who is able to access this file
// The upload folder shouldn't be able to upload any kind of script, just in case.
// If you're not sure, hire a professional that takes care of adjusting the server configuration as well as this script for you.
// (I am not such professional)
// Configuration Options: Change these to alter the way files being written works
$overwriteFiles = false;
//THESE SETTINGS ONLY MATTER IF $overwriteFiles is FALSE
//Seperator between the name of the file and the generated ending.
$keepFilesSeperator = "-";
//Use "number" or "random". "number" adds a number, "random" adds a randomly generated string.
$keepFilesAddonType = "random";
//Only usable when $keepFilesAddonType is "number", this specifies where the number starts iterating from.
$keepFilesNumberStart = 1;
//Only usable when $keepFilesAddonType is "random", this specifies the length of the string.
$keepFilesRandomLength = 4;
//END FILE OVERWRITE FALSE SETTINGS
// Step 1: change the true for whatever condition you use in your environment to verify that the user
// is logged in and is allowed to use the script
if (true) {
echo("You're not allowed to upload files");
die(0);
}
// Step 2: Put here the full absolute path of the folder where you want to save the files:
// You must set the proper permissions on that folder (I think that it's 644, but don't trust me on this one)
// ALWAYS put the final slash (/)
$basePath = "/home/user/public_html/example/pages/projects/uploader/files/";
// Step 3: Put here the Url that should be used for the upload folder (it the URL to access the folder that you have set in $basePath
// you can use a relative url "/images/", or a path including the host "http://example.com/images/"
// ALWAYS put the final slash (/)
$baseUrl = "http://example.com/pages/projects/uploader/files/";
// Done. Now test it!
// No need to modify anything below this line
//----------------------------------------------------
// ------------------------
// Input parameters: optional means that you can ignore it, and required means that you
// must use it to provide the data back to CKEditor.
// ------------------------
// Optional: instance name (might be used to adjust the server folders for example)
$CKEditor = $_GET['CKEditor'] ;
// Required: Function number as indicated by CKEditor.
$funcNum = $_GET['CKEditorFuncNum'] ;
// Optional: To provide localized messages
$langCode = $_GET['langCode'] ;
// ------------------------
// Data processing
// ------------------------
// The returned url of the uploaded file
$url = '' ;
// Optional message to show to the user (file renamed, invalid file, not authenticated...)
$message = '';
// in CKEditor the file is sent as 'upload'
if (isset($_FILES['upload'])) {
// Be careful about all the data that it's sent!!!
// Check that the user is authenticated, that the file isn't too big,
// that it matches the kind of allowed resources...
$name = $_FILES['upload']['name'];
//If overwriteFiles is true, files will be overwritten automatically.
if(!$overwriteFiles)
{
$ext = ".".pathinfo($name, PATHINFO_EXTENSION);
// Check if file exists, if it does loop through numbers until it doesn't.
// reassign name at the end, if it does exist.
if(file_exists($basePath.$name))
{
if($keepFilesAddonType == "number") {
$operator = $keepFilesNumberStart;
} else if($keepFilesAddonType == "random") {
$operator = bin2hex(openssl_random_pseudo_bytes($keepFilesRandomLength/2));
}
//loop until file does not exist, every loop changes the operator to a different value.
while(file_exists($basePath.$name.$keepFilesSeperator.$operator))
{
if($keepFilesAddonType == "number") {
$operator++;
} else if($keepFilesAddonType == "random") {
$operator = bin2hex(openssl_random_pseudo_bytes($keepFilesRandomLength/2));
}
}
$name = rtrim($name, $ext).$keepFilesSeperator.$operator.$ext;
}
}
move_uploaded_file($_FILES["upload"]["tmp_name"], $basePath . $name);
// Build the url that should be used for this file
$url = $baseUrl . $name ;
// Usually you don't need any message when everything is OK.
// $message = 'new file uploaded';
}
else
{
$message = 'No file has been sent';
}
// ------------------------
// Write output
// ------------------------
if (!$message) {
echo "{
\"uploaded\": true,
\"url\": \"$url\"
}";
} else {
echo "{
\"uploaded\": false,
\"error\": {
\"message\": \"$message\"
}
}";
}
第29行的判斷請依照需求處理。
$basePath
跟 $baseUrl
請依照實際伺服器狀況做調整。
參考資料:
Simple Upload Adapter
https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/simple-upload-adapter.html
How to do CKEditor 5 Image Uploading?
https://stackoverflow.com/a/53060017/4865172
CKEditor, Image Upload (filebrowserUploadUrl)
https://stackoverflow.com/questions/2115302/ckeditor-image-upload-filebrowseruploadurl/44553006#44553006