Server-side Image Upload in TinyMCE Editor using PHP

Image upload is a common feature in the WYSIWYG HTML editor. If you’re using TinyMCE editor in the textarea, the image can be easily inserted into the editor. TinyMCE HTML editor provides an easy option to upload and insert images in the editor as BLOB data type. But it takes time to render BLOB images on the browser. So, server-side upload is always a better option to insert images in a TinyMCE editor.

TinyMCE editor supports local file picking and image uploading. But, to make these features functional you are required to do some settings in the TinyMCE configuration options. Also, the server-side upload handler is required to upload image file to the server. In this tutorial, we will show you how to allow the user to upload images in TinyMCE editor using PHP.

In this example, we will go through the image upload handling process in the TinyMCE editor with PHP. Also, demonstrates the integration of the upload image feature in TinyMCE using images_upload_handler callback and PHP upload handler script. With this feature, the user can upload images from the computer and insert them into the TinyMCE editor. Also, a friendly user interface (UI) will be provided to simplify the image upload by dropping it from the computer.

HTML Code

Define a textarea element (myTextarea) to add TinyMCE HTML Editor on the webpage.

<textarea id="myTextarea"></textarea>

JavaScript Code

First, include the JS library of the TinyMCE plugin.

<script src="tinymce/tinymce.min.js"></script>

Define image upload handler callback using JavaScript.

  • The selected file is posted to the server-side script (upload.php) to process upload functionality.
  • This upload handler function provides 2 events, blobInfo and progress.
  • On success, the uploaded file path is retrieved from the JSON object (json.location).
const image_upload_handler_callback = (blobInfo, progress) => new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open('POST', 'upload.php');
    
    xhr.upload.onprogress = (e) => {
        progress(e.loaded / e.total * 100);
    };
    
    xhr.onload = () => {
        if (xhr.status === 403) {
            reject({ message: 'HTTP Error: ' + xhr.status, remove: true });
            return;
        }
      
        if (xhr.status < 200 || xhr.status >= 300) {
            reject('HTTP Error: ' + xhr.status);
            return;
        }
      
        const json = JSON.parse(xhr.responseText);
      
        if (!json || typeof json.location != 'string') {
            reject('Invalid JSON: ' + xhr.responseText);
            return;
        }
      
        resolve(json.location);
    };
    
    xhr.onerror = () => {
      reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
    };
    
    const formData = new FormData();
    formData.append('file', blobInfo.blob(), blobInfo.filename());
    
    xhr.send(formData);
});

Initialize TinyMCE and attach editor to the textarea element specified in the selector option. The following configuration options enable the local file picker and image upload feature in the TinyMCE editor.

  • Enable the image plugin and add the image upload button to the editor toolbar.
  • Set the server-side upload handler script URL (upload.php) in the images_upload_url option. Once this config is defined, an Upload tab will appear in the Image Dialog.
  • Set the image upload handler callback in the images_upload_handler option.
tinymce.init({
    selector: '#myTextarea',
    plugins: 'image',
    toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | image',
    
    // without images_upload_url set, Upload tab won't show up
    images_upload_url: 'upload.php',
    
    // override default upload handler to simulate successful upload
    images_upload_handler: image_upload_handler_callback
});

PHP Upload Handler (upload.php)

This upload.php file handles the server-side image upload functionality using PHP.

  • Specify the origins that are allowed to post HTTP requests to this handler script and upload images to the server.
  • Validate the origin of the HTTP request and accept only allowed origins.
  • Check whether the file was uploaded via HTTP POST using PHP is_uploaded_file() function.
  • Sanitize input file name using preg_match() function in PHP.
  • Verify the extension of the file using pathinfo() function in PHP.
  • Upload file to the server using move_uploaded_file() function in PHP.
  • Respond to the successful upload with JSON. Use a location key to specify the path to the saved image resource.
<?php 

// Only these origins are allowed to upload images
$accepted_origins = array("http://localhost""https://www.codexworld.com""http://192.168.1.1""http://example.com");

// Set the upload folder
$imageFolder "uploads/";

if (isset(
$_SERVER['HTTP_ORIGIN'])) {
    
// same-origin requests won't set an origin. If the origin is set, it must be valid.
    
if (in_array($_SERVER['HTTP_ORIGIN'], $accepted_origins)) {
        
header('Access-Control-Allow-Origin: ' $_SERVER['HTTP_ORIGIN']);
    } else {
        
header("HTTP/1.1 403 Origin Denied");
        return;
    }
}

// Don't attempt to process the upload on an OPTIONS request
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    
header("Access-Control-Allow-Methods: POST, OPTIONS");
    return;
}

reset ($_FILES);
$temp current($_FILES);
if (
is_uploaded_file($temp['tmp_name'])){
    
/*
      If your script needs to receive cookies, set images_upload_credentials : true in
      the configuration and enable the following two headers.
    */
    // header('Access-Control-Allow-Credentials: true');
    // header('P3P: CP="There is no P3P policy."');

    // Sanitize input
    
if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/"$temp['name'])) {
        
header("HTTP/1.1 400 Invalid file name.");
        return;
    }

    
// Verify extension
    
if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif""jpg""jpeg""png"))) {
        
header("HTTP/1.1 400 Invalid extension.");
        return;
    }

    
// Accept upload if there was no origin, or if it is an accepted origin
    
$filetowrite $imageFolder $temp['name'];
    if(
move_uploaded_file($temp['tmp_name'], $filetowrite)){
        
// Determine the base URL
        
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' "https://" "http://";
        
$baseurl $protocol $_SERVER["HTTP_HOST"] . rtrim(dirname($_SERVER['REQUEST_URI']), "/") . "/";
    
        
// Respond to the successful upload with JSON.
        // Use a location key to specify the path to the saved image resource.
        // { location : '/your/uploaded/image/file'}
        
echo json_encode(array('location' => $baseurl $filetowrite));
    }else{
        
header("HTTP/1.1 400 Upload failed.");
        return;
    }
} else {
    
// Notify editor that the upload failed
    
header("HTTP/1.1 500 Server Error");
}

?>

Image Upload Dialog in TinyMCE

The image icon in the editor’s toolbar opens a dialog box for the image upload. In the Upload tab, you can select an image from the computer or drag and drop the image directly. The image will be uploaded to the server and HTML will be inserted into the editor.

tinymce-editor-drag-drop-image-upload-dialog-php-codexworld

How to Export TinyMCE Content to MS Word Document

Conclusion

This example uses the latest version of the TinyMCE plugin (v6). You can add a responsive Rich Text Editor to the website and integrate the image upload feature in TinyMCE 6 using PHP. Not only the image upload but also you can set the description and change the width/height of the image before inserting it in the TinyMCE editor.

Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request

6 Comments

  1. Guillermo Esquivel Said...
  2. Yunus Said...
  3. Esh Said...
  4. Jethro Said...
  5. Zalaya Said...
  6. Alex Said...

Leave a reply

keyboard_double_arrow_up