5
votes

I'm using the ckeditor to do the HTML text. When I paste an image in it, the ckeditor do the upload of image. I have used like pdf library the TCPDF and MPDF, I got two distinct errors, one in each library.

mPDF error: IMAGE Error (SOURCE-IMAGE): Error parsing temporary file image object created with GD library to parse PNG image

TCPDF ERROR: [Image] Unable to get the size of the image: (SOURCE-IMAGE)

My code for upload image when paste in ckeditor is as follows:

<?php
session_start();

class image{

    private $save_path = 'uploads/';
    private $image_string = '';
    private $image_name = '';
    private $image;
    private $response = array();

    public $loaded = false;

    public function __construct(){
        $this->response = array(
            'error' => 1,
            'message' => 'unknown error.'
        );

        $this->image_string = filter_input(INPUT_POST, 'image');


        $ext = substr($this->image_string,11,3);
        $randomLetters = $rand = substr(md5(microtime()),rand(0,26),6);
        $imgnumber = count(scandir($this->save_path));

        $this->image_name = "$imgnumber$randomLetters.$ext";

        if(!empty($this->image_name) && !empty($this->image_string)){
            $this->loaded = true;
        }
    }

    public function save(){
        if(!empty($this->image_name) && !empty($this->image_string)){
            return $this->progress();
        }
        else{
            $this->response['message'] = 'Error. Not all required infor is given.';
            $this->response['error'] = 1;
            return $this->response;
        }
    }

    private function progress(){
        $imgarr = explode(',', $this->image_string);
        if(!isset($imgarr[1])){
            $this->response['message'] = 'Error on post data image. String is not the expected string.';
            $this->response['error'] = 1;
            return $this->response;
        }
        $this->image = base64_decode($imgarr[1]);
        if(!is_null($this->image)){
            $file = $this->save_path . $this->image_name;
            if(file_exists($file)){
                $this->response['message'] = 'Image already exists on server.';
                $this->response['error'] = 1;
                return $this->response;
            }
            if(file_put_contents($file, $this->image) !== false){
                $this->response['message'] = 'Image saved to server';
                $this->response['error'] = 0;
                $this->response['source'] = '../plugins/imageuploader/'.$file;
                return $this->response;
            }
            else{
                $this->response['error'] = 1;
                $this->response['message'] = 'Error writing file to disk';
                return $this->response;
            }
        }
        else{
            $this->response['message'] = 'Error decoding base64 string.';
            return $this->response;
        }
    }
}

$img = new image();
if($img->loaded){
    $result = $img->save();
    echo json_encode($result);
}
else{
    $result = array(
        'error' => 1,
        'message' => 'Not all post data given'
    );
    echo json_encode($result);
}
?>

What can cause this error?

Edit: the ajax code is part of ckeditor code, the part is here, the image comes like the base64 code:

function h(a, d) {
        if (a && "function" === typeof a.getAsFile) { 
            var b = a.getAsFile(), c = new FileReader;
            c.onload = function (a) {
               var fd = new FormData();
                fd.append('image', a.target.result); //the base64 of image with format equals in src of tag img in html
                $.ajax({
                    type: 'POST',
                    url: '../plugins/imageuploader/ajaxupload.php',
                    data: fd,
                    processData: false,
                    contentType: false,
                    dataType: 'json'
                }).done(function(data) {
                    if((data.error == 0) && (typeof data.source != 'undefined')){
                        //alert(data.source);
                        var b = d.document.createElement("img", {attributes: {src: data.source}});
                        setTimeout(function () {
                            d.insertElement(b)
                        }, 10)
                    }else{
                        alert('Não foi possível carregar a imagem:\nErro - '+data.message);  // show the message error if it can't be uploaded.
                    }
                });
            };
            c.readAsDataURL(b);
        }
  }
 
2
Have you checked (write)permissions on the directory where the image file is stored? - Johan
The image is uploaded, i set the write permissions like true, this are ok, the way to upload the images is: when paste image, i get the base64 encode of image, then i write in a file the base64 decoded string @Johan - alexandre9865
Hi, can you show the base64 encoded string of the image ? - mandar
@mandar The image that works fine is this: preventiva.med.br/Teste/ckeditor/plugins/imageuploader/uploads/… The image that doesn't work is that: preventiva.med.br/Teste/ckeditor/plugins/imageuploader/uploads/… Both images are an example only. The problem occurrs with all whose upload is with ajax. - alexandre9865
the base64 from image with error is this jsfiddle.net/alexandre9865/efnu4otr this big code is in base64_decode() function of the php there. - alexandre9865

2 Answers

4
votes

Before sending the data you need to encode some characters of the base64. For example + and = will cause the code to behave differently. Or use hex values intead of base64 encode.

EDIT: Depending on the form. But you can set a button to convert the textarea using this function:

function escapeChars(){
   var value = document.getElementById("myTextarea").value;
   value = value.replace("+", "%2b");
   value = value.replace("/", "%2f");
   value = value.replace("=", "%3d");
   document.getElementById("myTextarea").value = value;
}

or if you use ajax just use the function before sending.

In php, revert the changes:

$this->image_string = str_replace(array("%2b", "%2f", "%3d"), array("+", "/", "="), $_POST['image']);

instead of $this->image_string = filter_input(INPUT_POST, 'image');

EDIT2 In php:

<?php
session_start();

class image{

    private $save_path = 'uploads/';
    private $image_string = '';
    private $image_name = '';
    private $image;
    private $response = array();

    public $loaded = false;

    public function __construct(){
        $this->response = array(
            'error' => 1,
            'message' => 'unknown error.'
        );

        $this->image_string = str_replace(array("%2b", "%2f", "%3d"), array("+", "/", "="), $_POST['image']);

        $imgarr = explode(',', $this->image_string);
        if(!isset($imgarr[1])){
            return;
        }
        $this->image_string = $imgarr[1];

        $namearray = explode('.', $imgarr[0]);
        $ext = end($namearray);
        if(!in_array($ext, array('jpg','png')))
            return false;

        $randomLetters = $rand = substr(md5(microtime()),rand(0,26),6);
        $imgnumber = count(scandir($this->save_path));

        $this->image_name = "$imgnumber$randomLetters.$ext";

        if(!empty($this->image_name) && !empty($this->image_string)){
            $this->loaded = true;
        }
    }

    public function save(){
        if(!empty($this->image_name) && !empty($this->image_string)){
            return $this->progress();
        }
        else{
            $this->response['message'] = 'Error. Not all required infor is given.';
            $this->response['error'] = 1;
            return $this->response;
        }
    }

    private function progress(){

        $this->image = base64_decode($this->image);
        if(!is_null($this->image)){
            $file = $this->save_path . $this->image_name;
            if(file_exists($file)){
                $this->response['message'] = 'Image already exists on server.';
                $this->response['error'] = 1;
                return $this->response;
            }
            if(file_put_contents($file, $this->image) !== false){
                $this->response['message'] = 'Image saved to server';
                $this->response['error'] = 0;
                $this->response['source'] = '../plugins/imageuploader/'.$file;
                return $this->response;
            }
            else{
                $this->response['error'] = 1;
                $this->response['message'] = 'Error writing file to disk';
                return $this->response;
            }
        }
        else{
            $this->response['message'] = 'Error decoding base64 string.';
            return $this->response;
        }
    }
}

$img = new image();
if($img->loaded){
    $result = $img->save();
    echo json_encode($result);
}
else{
    $result = array(
        'error' => 1,
        'message' => 'Not all post data given'
    );
    echo json_encode($result);
}
?>

in Javascript before sending ajax:

function escapeChars(value){
   value = value.replace("+", "%2b");
   value = value.replace("/", "%2f");
   value = value.replace("=", "%3d");
   return value;
}

Then you can use escapeChars in the value.

1
votes

If the image is uploaded to server successfully and pdf library is throwing the error.

The possible reason here could be that the pdf library is unable to read the image file, make sure the path to image file is correct.

As the pdf library converts html to pdf it must be expecting a relative path eg:-

 <img src="http://yourdomain/image_path">

I have tested tcpdf library and found the same issue and same error if the library was unable to find the image.