0

I'm using the Cropper JS library and then class.upload.php on an image upload project. I've got everything working except when the PHP script processes the upload, it saves the uncropped version of the image. If I 'inspect' the file input in Chrome after I've performed the crop, the src is the cropped image, so I can't figure out for the life of me why it's receiving the original uncropped version.

The HTML looks like this. It uses Bootstrap & JQuery, but I'm omitting that to avoid bloat.

    <input type="file" class="upload-input" name="imageFile" accept="image/*" style="display:none;" id="input-1">
    <div class="input-group mb-3">
        <input type="text" class="form-control" id="filename-1" readonly placeholder="Upload your show image (Required)" style="width:100%;">
        <div class="input-group-btn">
            <button class="btn btn-outline-secondary upload-button" type="button" data-ratio="1/1">Select</button>
        </div>
    </div>
    
    <!-- Modal For Cropper -->
    <div class="modal fade photo-cropper" tabindex="-1" aria-labelledby="cropperModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h1 class="modal-title fs-5" id="cropperModalLabel">Crop your image</h1>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div class="upload-preview">
                        <img class="upload-image-preview" style="display: block; max-width: 100%;">
                        <div class="photo-cropper-controls">
                            <i class="fa fa-check-square" id="crop-confirm" aria-hidden="true"></i>
                            <i class="fa fa-window-close" id="crop-cancel" aria-hidden="true"></i>
                        </div>
                    </div>     
                </div>
            </div>
        </div>
    </div>

Here's the JS that controls Cropper

    $(document).on('click', '.upload-button', function(e) {
        var ratio = $(this).data('ratio');
        var activeInput = $('#input-1');
        activeInput.click();
        $(activeInput).change(function() {
            if(this.files && this.files[0]) {
                var imageFile = this.files[0];
                var reader = new FileReader();
                reader.onload = function (e) {
                    $('.photo-cropper').modal('show');
                    $(document).on('shown.bs.modal', function (f) {
                        $('.upload-image-preview').attr('src', e.target.result);
                        $('.photo-cropper-controls').show();
                        $('.upload-image-preview').data('target', '#input-1');
                        $('.upload-image-preview').cropper('destroy');
                        $('.upload-image-preview').cropper({
                            aspectRatio: eval(ratio),
                            viewMode: 1
                        });
                    });
                }
                reader.readAsDataURL(imageFile);
            }
        });
    });

    $(document).on('click', '#crop-confirm', function() {
        var target = $('.upload-image-preview').data('target');
        var imageData = $('.upload-image-preview').cropper('getCroppedCanvas', {maxWidth: 990}).toDataURL('image/jpeg');
        $('.photo-cropper').modal('hide');
        $(document).on('hidden.bs.modal', function (f) {
            $('.upload-image-preview').cropper('destroy');
        });
        $(target).attr('src', imageData);
        var filename = $(target).val().split('\\').pop();
        $('#filename-1').val(filename);
    });

And finally, the PHP that deals with the posted form

    if(!empty($_FILES['imageFile'])) {
            require_once('assets/plugins/class.upload.php');
            $handle = new upload($_FILES['imageFile']);
            if ($handle->uploaded) {
                $handle->file_safe_name = true;
                $handle->allowed = array('image/*');
                $handle->image_ratio_y = true;
                $handle->image_x = 800;
                $handle->process('/upload/path/');
                if ($handle->processed) {
                    $image = $handle->file_dst_name;
                }
            }
    }

The basic method is click the .upload-button which clicks the hiding file input, then opens a Bootstrap modal and initialises Cropper with the selected image. When you've finished cropping, clicking #crop-confirm creates the DataURL, closes the modal, and puts the imageData in the file input. Submitting the form sends the data to the PHP with the image in the imageFile field. All ok so far? So why is the file it saves the original uncropped image?

I'm clearly missing something really obvious...

PeteSE4
  • 413
  • 3
  • 18
  • _"If I 'inspect' the file input in Chrome after I've performed the crop, the src is the cropped image"_ - a file input field does not even have a `src`. I am guessing what you are actually inspecting, is the `img.upload-image-preview` used to _preview_ the cropped result? Well an image is not a file upload field, and doesn't send any data to the server. – CBroe Oct 14 '22 at 07:59
  • You can not do this, by simply letting this form submit "normally" - you will need to use AJAX/fetch to send the data to the server, and use `FormData` to put your cropped image data into the request in a form that PHP will recognize as a file upload. (Alternatively, you could base64 encode the image data, and stick it into a hidden form field, then you can submit the form normally afterwards. But then you won't find the image in `$_FILES`, but would have to base64 decode the string you are receiving yourself.) – CBroe Oct 14 '22 at 08:01

0 Answers0