Pre- resize multiple images before uploading from client side Jquery Laravel

Viewed 670

the code is partially working, it collects images and resize them into base64 in a loop but i am not getting the images to send when i append it in form... but when i post simple pictures by removing the resize function it sends every picture... i don't understand that what is the issue..

heres the html:

Upload Pictures <input type="file" name="file[]" id="file" multiple/>

heres i am collecting pictures:

<script>
        $(document).on('change','#file',function(){
            files = this.files;
            ajax_file_upload(files);
        });
</script>

heres the code where i am resizing them in a loop and sending them through ajax: note: in the resize function i am getting the resized picture in the console... i will attach a picture of console as well...

console image

<script>
        function ajax_file_upload(file_obj) {

            if(file_obj != undefined) {
               var status='true';
                var image = new FormData();
                var match = ['image/jpeg', 'image/png', 'image/jpg'];
                for(i=0; i<file_obj.length; i++) {
                    var fileType = file_obj[i].type;
                    // alert(fileType)
                    if(!((fileType == match[0]) || (fileType == match[1]) || (fileType == match[2]) || (fileType == match[3]) || (fileType == match[4]) || (fileType == match[5]))){
                        var status='false';
                    }
                    
                    resizeImages(file_obj[i],function(dataUrl){
                        image.append('file[]',dataUrl);
                    });
                }
                $.ajax({
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    },
                    url: "{{ route('resize') }}",
                    type: "POST",
                    // data: {pictures:pictures},
                    data:image,
                    cache:false,
                    processData: false,
                    contentType: false,
                    datatype:'html',
                    success: function (response) {
                        return true;
                            }
                        });
                }
        }
    </script>

here the resize function i am using to resize the images and getting dataurl:

<script>
        function resizeImages(file,complete) {
            // read file as dataUrl
            ////////  2. Read the file as a data Url
            var reader = new FileReader();
            // file read
            reader.onload = function(e) {
                // create img to store data url
                ////// 3 - 1 Create image object for canvas to use
                var img = new Image();
                img.onload = function() {
                    /////////// 3-2 send image object to function for manipulation
                    complete(resizeInCanvas(img));
                };
                img.src = e.target.result;
            }
            // read file
            reader.readAsDataURL(file);

        }



        function resizeInCanvas(img){
            /////////  3-3 manipulate image
            var perferedWidth = 1200;
            var ratio = perferedWidth / img.width;
            var canvas = $("<canvas>")[0];
            canvas.width = img.width * ratio;
            canvas.height = img.height * ratio;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0,0,canvas.width, canvas.height);
            //////////4. export as dataUrl
            return canvas.toDataURL('image/jpeg', 0.6);
        }
    </script>

this function is working perfectly... now when i send it to the server it doesn't posts anything.. tried it many ways researched but didn't got anything.. please guide me thanks

1 Answers

So, I've no help but I managed to solve the issue by using tweeks.... I'm posting them so it can help someone... Thanks

here i am picking the picture and passing it to be resized and pushing them in array:

 $(document).on('change','#selectfile',function(){
            file_obj = this.files;
            pictures_array(file_obj);
    });

here the function for resizing and store it in array, i'm here restricting ajax function from running until the in array count will not equal the length of files with some validation..:

function pictures_array(file_obj){
            var image_count = $('.sequence').length-1;
            count = file_obj.length;
            var new_count = image_count+count;
            
            console.log(image_count,new_count,count);
            if(new_count<=15){
            $('.ajax-loader').css("visibility", "visible");
            
            pictures = [];


            for(i=0; i<file_obj.length; i++) {
                var fileType = file_obj[i].type;
                var match = ['image/jpeg', 'image/png', 'image/jpg'];
                if(!((fileType == match[0]) || (fileType == match[1]) || (fileType == match[2]) || (fileType == match[3]) || (fileType == match[4]) || (fileType == match[5]))){
                    var status='false';
                }
                resizeImages(file_obj[i],function(dataUrl){
                    var data = dataUrl;
                    pictures.push(data);
                    if(!--count) {
                        ajax(pictures);
                    }

                });

            }
            
            }else{
                $('#max_limit').html(15);
                $('#limit').show();
                $('html, body').animate({
                        scrollTop: $(".main-image").offset().top
                    }, 2000);
                $('#selectfile').val('');
                $('#selectfile1').val('');    
            }
}

heres the ajax call: i am apending the base64 version of pictures using for loop in the file[]:

function ajax(pictures) {
    // console.log(pictures);
    
    var image = new FormData();
    var pictures = pictures;
    for (var i = 0; i < pictures.length; i++) {
        image.append('file[]',pictures[i]);
    }


    $.ajax({
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
            // 'Content-Type': 'multipart/form-data',
        },
        url: "{{ route('images_private.store',$row->id) }}",
        type: "POST",
        data: image,
        cache: false,
        processData: false,
        contentType: false,
        datatype: 'html',
        beforeSend: function(){
                    $('.ajax-loader').css("visibility", "visible");
                },
                success:function(response) {
                    $('#selectfile').val('');
                    $('#selectfile1').val('');
                    $('#appendhtml').html(response);
                    // $('#appendhtml').load('#appendhtml');
                    setTimeout(function() {
                        toastr.options = {
                            closeButton: true,
                            progressBar: true,
                            showMethod: 'slideDown',
                            timeOut: 4000
                        };
                        toastr.success('Images uploaded successfully');
                    }, 1300);
                    $("#other-image-main").sortable({
                        cursor: 'move',
                        opacity: 0.6,
                        update: function() {
                            sendOrderToServer();
                        }
                    });

                },
                complete: function(){
                    $('.ajax-loader').css("visibility", "hidden");
                    $('#valid_image_type').hide();

                },
    });
}

and then the last step in the controller: here i am decoding the base64 to jpeg file and storing it into the server:

if(!File::isDirectory($path)){

        File::makeDirectory($path, 0777, true, true);

    }
        if($request->has('file')){
        foreach ($request->file as $image){
            $position++;
            list($type, $image) = explode(';', $image);
            list(, $image)      = explode(',', $image);

            $image = base64_decode($image);

            $source_img = imagecreatefromstring($image);
            $filename= uniqid() . '.jpg';
            $filepath = $path.$filename ;
            $imageSave = imagejpeg($source_img, $filepath);
            
            ImagesPrivate::create([
                'user_id'=>$id,
                'owner_id'=>$auth,
                'name'=>$filename,
                'position'=>$position,
                'position_change'=>$position,
                'delete' => 'pending',
                ]);
            
        }
        }

So, in the end 4.8MB picture is now weigh 316KB thats a success,,,

i am posting this because i haven't found anything like that and it took me time to do this,,, may be i haven't researched properly but this is how i manage to upload multiple images pre-resized on client side without any trigger button... cuts uploading time to 90%...

Hope that helps someone Thanks Regards

Related