Black Friday sale is now on! 50% off Laravel: The Modular Way. Learn more

Adding a Drag and Drop image uploads & custom upload script to CKEditor 4

David Carr

CKEditor elFinder PHP & MySQL Tutorials

  • Putting it all Together:
  • In order to add drag and drop image upload to CKEditor make sure you've included the Upload Image plugin to CKEditor.

    To enable drag and drop and file uploads there are 2 settings that need to be enabled. go to ckeditor/config.js and add these settings:

    In this case, I'm using elFinder for the filemanager

    config.filebrowserUploadUrl = '/elfinder/php/upload.php?type=file';
    config.imageUploadUrl = '/elfinder/php/upload.php?type=image';

    The filebrowserUploadUrl is for enabling file uploads from the link and image dialog boxes.
    The imageUploadUrl is for allowing drag and drop uploads.

    You could send these to different files, I've chosen to deal with both cases in the same file called upload.php that I've placed in elfinder/php/upload.php

    The first task to take care of is ensuring the post request has come from CKEditor and not somewhere else. CKEditor comes with CSRF token out the box so we can use that and compare the value it stores in a cookie against the post request:

    //if csrf passes
    if ($_COOKIE['ckCsrfToken'] == $_POST['ckCsrfToken']) {

    Now define sizes so we can later use them for calculating file upload sizes. 

    Also set up the base variables:

    //define file sizes
    define('KB', 1024);
    define('MB', 1048576);
    define('GB', 1073741824);
    define('TB', 1099511627776);
    
    //set variables 
    $tmpName  	   = $_FILES['upload']['tmp_name'];
    $filename 	   = $_FILES['upload']['name'];
    $size 		   = $_FILES['upload']['size'];
    $filePath      = "../files/" . date('d-m-Y-H-i-s').'-'.$filename;
    $fileExtension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    $type 		   = $_GET['type'];
    $funcNum 	   = isset($_GET['CKEditorFuncNum']) ? $_GET['CKEditorFuncNum']: null;

    $tmpName - the tempory name assigned to uploaded files.
    $filename - is the name of the file eg logo.png.
    $size - is the size in bytes of the file.
    $filePath - is where you want to store the file, This code goes up a directory into the files folder and applies a datetime to the start of the filename (optional).
    $fileExtension - is the extension of the file.
    $type - will be either file or image depending on the action on the editor.
    $funcNum - comes from CKEditor and is needed when using the file callback.

    Depending on the type set the file extensions allowed to be uploaded.

    if ($type == 'image') {
    	$allowedfileExtensions = array('jpg', 'jpeg', 'gif', 'png');
    } else {
    	//file
    	$allowedfileExtensions = array('jpg', 'jpeg', 'gif', 'png', 'pdf', 'doc', 'docx');
    }

    Now check if the file/image is allowed otherwise set the error message and when its a file echo a javascript passing in the $funcNum, $filePath and $message. CKEditor will use these to alert the user. 
    For drag and drop uploads return an array containing uploaded 0 for fail, error with an array containing the error message.

    //contrinue only if file is allowed
    if (in_array($fileExtension, $allowedfileExtensions)) {
    
    } else {
    
    	$error = 'The file type uploaded is not allowed.';
    
    	if ($type == 'file') {
    		$funcNum = $_GET['CKEditorFuncNum'];
    		$message = $error;
    
    		echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath', '$message');</script>";
    		exit();
    	}
    
        
        $data = array('uploaded' => 0, 'error' => array('message' => $error));
    
    }

    Check the size of the upload, I've chosen to let uploads no bigger than 20MB (bear in mind your server but be allowed to upload files as big as you've set here)

    //contunie if file is less then the desired size
    if ($size < 20*MB) {
    
    
    } else {
    
    	$error = 'The file must be less than 20MB';
    
    	if ($type == 'file') {
    		$message = $error;
    
    		echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath', '$message');</script>";
    		exit();
    	}
    
    	$data = array('uploaded' => 0, 'error' => array('message' => $error));
    
    }

    Attempt to upload the file/image

    Since the $filePath will contain ../files the end URL will be ../files/logo.png I prefer to have absolute paths so using str_replace to remove ../ and add the domain address to the $filePath

    Set the $data array to uploaded 1 meaning success and the filename and url.

    if (move_uploaded_file($tmpName, $filePath)) {
    
    	$filePath = str_replace('../', 'http://filemanager.localhost/elfinder/', $filePath);
        $data = ['uploaded' => 1, 'fileName' => $filename, 'url' => $filePath];
    
        if ($type == 'file') {
    
    		echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath');</script>";
    		exit();
    	}
    
    } else {
    
        $error = 'There has been an error, please contact support.';
    
        if ($type == 'file') {
    		$message = $error;
    
    		echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath', '$message');</script>";
    		exit();
    	}
    
        $data = array('uploaded' => 0, 'error' => array('message' => $error));
    
    }

    The last item is to return the $data and json_encode it.

    echo json_encode($data);

    Putting it all Together:

    <?php
    //if csrf passes
    if ($_COOKIE['ckCsrfToken'] == $_POST['ckCsrfToken']) {
    
    	//define file sizes
    	define('KB', 1024);
    	define('MB', 1048576);
    	define('GB', 1073741824);
    	define('TB', 1099511627776);
    
    	//set variables 
    	$tmpName  	   = $_FILES['upload']['tmp_name'];
    	$filename 	   = $_FILES['upload']['name'];
    	$size 		   = $_FILES['upload']['size'];
    	$filePath      = "../files/" . date('d-m-Y-H-i-s').'-'.$filename;
    	$fileExtension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    	$type 		   = $_GET['type'];
    	$funcNum 	   = isset($_GET['CKEditorFuncNum']) ? $_GET['CKEditorFuncNum']: null;
    
    	if ($type == 'image') {
    		$allowedfileExtensions = array('jpg', 'jpeg', 'gif', 'png');
    	} else {
    		//file
    		$allowedfileExtensions = array('jpg', 'jpeg', 'gif', 'png', 'pdf', 'doc', 'docx');
    	}
    
    	//contrinue only if file is allowed
    	if (in_array($fileExtension, $allowedfileExtensions)) {
    
    		//contunie if file is less then the desired size
    		if ($size < 20*MB) {
    
    			if (move_uploaded_file($tmpName, $filePath)) {
    
    				$filePath = str_replace('../', 'http://filemanager.localhost/elfinder/', $filePath);
    			    $data = ['uploaded' => 1, 'fileName' => $filename, 'url' => $filePath];
    
    			    if ($type == 'file') {
    
    					echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath');</script>";
    					exit();
    				}
    
    			} else {
    
    			    $error = 'There has been an error, please contact support.';
    
    			    if ($type == 'file') {
    					$message = $error;
    
    					echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath', '$message');</script>";
    					exit();
    				}
    
    			    $data = array('uploaded' => 0, 'error' => array('message' => $error));
    
    			}
    
    		} else {
    
    			$error = 'The file must be less than 20MB';
    
    			if ($type == 'file') {
    				$message = $error;
    
    				echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath', '$message');</script>";
    				exit();
    			}
    
    			$data = array('uploaded' => 0, 'error' => array('message' => $error));
    
    		}
    
    	} else {
    
    		$error = 'The file type uploaded is not allowed.';
    
    		if ($type == 'file') {
    			$funcNum = $_GET['CKEditorFuncNum'];
    			$message = $error;
    
    			echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$filePath', '$message');</script>";
    			exit();
    		}
    
    	    
    	    $data = array('uploaded' => 0, 'error' => array('message' => $error));
    
    	}
    
    	//return response
    	echo json_encode($data);
    }

    Now when you can drag and drop images on CKEditor then the uplpad.php script will be triggered and upload the file to the elfinder/php/files folder.

    Laravel Modules Book by David Carr

    Help support the blog so that I can continue creating new content!

    Subscribe to my newsletter

    Subscribe and get my books and product announcements.

    © 2009 - 2022 DC Blog. All code MIT license. All rights reserved.