Search code examples
jqueryajaxopencart-3cropit

How to upload serialized image data in jquery/php?


I'm trying to crop then upload images using http://scottcheng.github.io/cropit/ extension in OpenCart 3. But I don't know how to upload serialized image data.

Here is the HTML part of the code which actually is the code of Cropit extension:

<form action="#">
    <div class="image-editor">
        <input type="file" class="cropit-image-input">
        <div class="cropit-preview"></div>
        <div class="image-size-label">
            Resize image
        </div>
        <input type="range" class="cropit-image-zoom-input">
        <input type="hidden" name="image-data" class="hidden-image-data" />
        <button type="submit"><i class="fa fa-upload"></i> Submit</button>
    </div>
</form>

<div id="result">
    <code>$form.serialize() =</code>
    <code id="result-data"></code>
</div>

And the JQuery / Ajax script:

<script>
$(function() {
    $('.image-editor').cropit();

    $('form').submit(function() {

        // Move cropped image data to hidden input
        var imageData = $('.image-editor').cropit('export');
        $('.hidden-image-data').val(imageData);

        // Print HTTP request params
        var formValue = $(this).serialize();
        $('#result-data').text(formValue);

        // ^   the codes of Cropit extension
        // v   the codes of PHP/OC3 for uploading images

        $('#form-upload').remove();

        $('body').prepend('<form enctype="multipart/form-data" id="form-upload" style="display: none;"><input type="file" name="file[]" value="" multiple="multiple" /></form>');

        if (typeof timer != 'undefined') {
                clearInterval(timer);
        }

        timer = setInterval(function() {
            if (imageData != '') {
                clearInterval(timer);

                $.ajax({
                    url: 'index.php?route=common/filemanager/upload&user_token={{ user_token }}&directory={{ directory }}',
                    type: 'post',
                    dataType: 'json',
                    data: FormData(formValue), //new FormData($('#form-upload')[0]),
                    cache: false,
                    contentType: false,
                    processData: false,
                    beforeSend: function() {
                        $('#button-upload i').replaceWith('<i class="fa fa-circle-o-notch fa-spin"></i>');
                        $('#button-upload').prop('disabled', true);
                    },
                    complete: function() {
                        $('#button-upload i').replaceWith('<i class="fa fa-upload"></i>');
                        $('#button-upload').prop('disabled', false);
                    },
                    success: function(json) {
                        if (json['error']) {
                            alert(json['error']);
                        }

                        if (json['success']) {
                            alert(json['success']);

                            $('#button-refresh').trigger('click');
                        }
                    },
                    error: function(xhr, ajaxOptions, thrownError) {
                        alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
                    }
                });
            }
        }, 500);

        // Prevent the form from actually submitting
        return false;
    });
});
</script>

It's interesting that the page shows successful image upload message by clicking on Submit button, but not file actually gets upload.

UPDATE : More Information

Here is the PHP Upload function:

<?php
    public function upload() {
        $json = array();

        // Make sure we have the correct directory
        if (isset($this->request->get['directory'])) {
            $directory = rtrim(DIR_IMAGE . 'catalog/' . $store_folder_slash . $this->request->get['directory'], '/');
        } else {
            $directory = DIR_IMAGE . 'catalog' . $store_slash_folder;
        }

        // Check its a directory
        if (!is_dir($directory) || substr(str_replace('\\', '/', realpath($directory)), 0, strlen(DIR_IMAGE . 'catalog' . $store_slash_folder)) != str_replace('\\', '/', DIR_IMAGE . 'catalog' . $store_slash_folder)) {
            $json['error'] = $this->language->get('error_directory');
        }

        if (!$json) {
            // Check if multiple files are uploaded or just one
            $files = array();

//          if (!empty($this->request->files['file']['name']) && is_array($this->request->files['file']['name'])) {
//              foreach (array_keys($this->request->files['file']['name']) as $key) {
//                  $files[] = array(
//                      'name'     => $this->request->files['file']['name'][$key],
//                      'type'     => $this->request->files['file']['type'][$key],
//                      'tmp_name' => $this->request->files['file']['tmp_name'][$key],
//                      'error'    => $this->request->files['file']['error'][$key],
//                      'size'     => $this->request->files['file']['size'][$key]
//                  );
//              }
//          }

//          foreach ($files as $file) {
//              if (is_file($file['tmp_name'])) {
            if ($this->request->server['REQUEST_METHOD'] == 'POST') {
                // Sanitize the folder name
                $encoded = html_entity_decode($this->request->post['data'], ENT_QUOTES, 'UTF-8');

                //decode the url, because we want to use decoded characters to use explode
                $decoded = urldecode($encoded);

                //explode at ',' - the last part should be the encoded image now
                $exp = explode(',', $decoded);

                //we just get the last element with array_pop
                $base64 = array_pop($exp);

                //decode the image and finally save it
                $data = base64_decode($base64);

                if (is_file($data)) {
                    // Sanitize the filename
                    $filename = basename('test.jpg');
                    //$filename = basename(html_entity_decode($file['name'], ENT_QUOTES, 'UTF-8'));

                    if (!in_array(utf8_strtolower(utf8_substr(strrchr($filename, '.'), 1)), $allowed)) {
                        $json['error'] = $this->language->get('error_filetype');
                    }
                } else {
                    $json['error'] = $this->language->get('error_upload');
                }

                if (!$json) {
                    //move_uploaded_file($file, $directory . '/' . $filename);
                    file_put_contents($data, $directory . '/' . $filename);
                }
            }
        }

        if (!$json) {
            $json['success'] = $this->language->get('text_uploaded');
        }

        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }

which return this error:
PHP Warning: is_file() expects parameter 1 to be a valid path, string given

No idea how to figure it on !


Solution

  • At last I found and fixed the problem!

    The problem was using data: 'data=' + imageData, for sending data by AJAX. I changed it to: data: {base64data : imageData}

    $.ajax({
        url: 'index.php?route=common/filemanager/upload&user_token={{ user_token }}&directory={{ directory }}',
        type: 'post',
        dataType: 'json',
        data: {base64data : imageData},
        ...