I've recently needed an answer to this as well, and it took me several hours to figure it out, so I decided to resurrect this question with some more up-to-date information and a full answer.
Eventually I stumbled upon this tutorial that explained it to me pretty well. For stackoverflow sake, I will reiterate the tutorial here in case it is removed. I will also include some changes that I made to the tutorial that make this a more flexible solution.
Getting Started
Let's start with any of the releases of ckeditor, (Basic, standard, full, custom) the only requirement is that you have the addon image and filebrowser
(As of writing this, all packages include these 2 addons except for the basic one, but it can be added to the basic one)
After you upload necessary ckeditor files, make sure your installation is working.
Make sure you link your ckeditor.js file script <script src="ckeditor/ckeditor.js"></script>
and then initialize it like so:
$(document).ready(function() {
CKEDITOR.replace( 'editor1' );
});
<textarea name="editor1"></textarea>
CKEditor Configuration
Now we have to tell CKEditor that we want to enable uploading. You can do this by going into your ckeditor folder, and editing `config.js'. We need to add this line:
config.filebrowserUploadUrl = '/uploader/upload.php';
somewhere inside the main function E.G
CKEDITOR.editorConfig = function( config ) {
// Define changes to default configuration here. For example:
// config.language = 'fr';
// config.uiColor = '#AADC6E';
config.filebrowserUploadUrl = '/uploader/upload.php';
};
NOTE: This URL is from your project root. No matter where you load this file from, it will start at your site index. Meaning, if your URL is example.com, this URL leads to http://example.com/uploader/upload.php
After this, CKEditor configuration is done! That was easy eh?
In fact, if you go and test your image uploading again now, you will get an upload option, though it won't quite work yet.
Server Configuration
Now you'll notice in the step before this one that it ends with an upload.php
file. This is the part that stumped me, I figured there would be some default that can go with this but as far as I know there is not. Luckily, I found one that works, and I made some changes to it to allow more customization.
So let's go to the path that you supplied in the last step, for continuity in this tutorial I am going to use /uploader/upload.php
.
At this location, make a file called (you guessed it) upload.php
.
This file is going to handle our file uploads.
I will put in my custom upload class, but it's based on this github that I found and forked.
upload.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
// ------------------------
// We are in an iframe, so we must talk to the object in window.parent
echo "<script type='text/javascript'> window.parent.CKEDITOR.tools.callFunction($funcNum, '$url', '$message')</script>";
?>
The changes that I made to this class allow you to enable/disable file overwriting and gives you some options for when you don't want to overwrite files. The original class always overwrites with no options.
By default this class is set to keep all files, without overwriting. You can play around with those settings to better suit your needs.
If you'll notice, there is a section of code that is just an if(true)
statement, which is always true obviously
if (true) {
echo("You're not allowed to upload files");
die(0);
}
This is for security. This is where you should check if the user uploading is logged in/allowed to upload. If you're not worried about that, you can just remove these lines of code or set it to if(false)
(NOT RECOMMENDED)
You will also need to edit the $basePath
and the $baseUrl
variables to fit your servers needs, or else it will not work. Everything below that can be left alone unless you want to play around.
This class does not offer file protection, you may want to work with it some to make it more safe, so people can't upload scripts or viruses to your server.
I hope that this little tutorial helped someone, as I worked far too long on trying to get this to work for myself, and I hope I can save someone else some time.
There is also some neat troubleshooting steps on that tutorial which I linked above, that may be able to help you find what's going wrong if something is.