The front end realizes image compression and upload (compatible with ios10 system)

Posted by alevsky on Wed, 01 Jan 2020 17:22:31 +0100

Questions: in the near future, we need to make a demand for the front-end to obtain images and compress them, then upload them to the back-end server or upload them to oss, and then transfer the path to the back-end server. During compression, it is found that the system at or below IOS 10 is invalid. After verification, this is because when using the HTML canvas element. Toblob() method of canvas to create blob objects, there is no system at or below IOS 10 Method call.

Answer:

1. Realize front-end compression and upload

(1) HTML: picture preview box & input upload control

<div id="uploader">
     <!-- Show preview picture -->
     <!-- <div class="img_show"></div> -->
     <!-- Picture upload -->
     <div id="fileInput" class="img_uploader">
         <input id="imgUpload" type="file" name="imgs" accept="image/*"> 
     </div>
</div>

(2) Image upload and compression

// formdata object of form upload
var fd = new FormData();
// canvas for compressing pictures
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
var file = null;       // Image objects uploaded by users

/* Click input to upload the picture */
$("#fileupload").on('change', function (e) {  
    file = event.target.files[0];
    // Picture preview, load base64 picture
    var reader = new FileReader();
    reader.onload = (function (file) {
        return function (e) {
            var datainfo = this.result;
            img.src = datainfo;
            var html = '<div class="img_show" style="background-image:url('+ datainfo +')"></div>'
            $("#uploader").prepend(html);
            if ($("#uploader .img_showCurrent").length >= 2) {
                $("#fileInput").hide();
            } 
        };
    })(e.target.files[0]);
    reader.readAsDataURL(e.target.files[0]);

    // After loading base64 address image, draw canvas compressed image
    img.onload = function () {
        // Picture original size
        var originWidth = this.width;
        var originHeight = this.height;
        // Maximum size limit
        var maxWidth = 800, maxHeight = 800;
        // Target size
        var targetWidth = originWidth, targetHeight = originHeight;
        // Picture size exceeds the limit of 400x400
        if (originWidth > maxWidth || originHeight > maxHeight) {
             if (originWidth / originHeight > maxWidth / maxHeight) {
                 // Wider, size by width
                 targetWidth = maxWidth;
                 targetHeight = Math.round(maxWidth * (originHeight / originWidth));
             } else {
                 targetHeight = maxHeight;
                 targetWidth = Math.round(maxHeight * (originWidth / originHeight));
             }
        }
        // canvas zooms the picture
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        // Clear canvas
        ctx.clearRect(0, 0, targetWidth, targetHeight);
        // Picture compression
        ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
        // When there is no toBlob method in the canvas object prototype, add it manually
        if (!HTMLCanvasElement.prototype.toBlob) {
            Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
                value: function (callback, type, quality) {
                    var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
                        len = binStr.length,
                        arr = new Uint8Array(len);
                    for (var i=0; i<len; i++ ) {
                        arr[i] = binStr.charCodeAt(i);
                    }
                    callback( new Blob( [arr], {type: type || 'image/png'} ) );
                 }
            });
        }
        // canvas to blob and upload
        canvas.toBlob(function (blob) {
            fd.append('pic', blob)
        }, file.type||'image/png');
   };
})

(3) Upload picture

fd.append("uid", uids);
$.ajax({
     type: "post",
     url: baseUrl + "xxxx/xxxxx",
     data: fd, 
     dataType: "json",
     processData: false,  // processData and contentType need to be set to false
     contentType: false,
     async: false,
     success: function (res) {
         // ... ...       
     }
})

2. Compatible with ios10 system

// When there is no toBlob method in the canvas object prototype, add it manually
if (!HTMLCanvasElement.prototype.toBlob) {
    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
        value: function (callback, type, quality) {
            var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
                len = binStr.length,
                arr = new Uint8Array(len);
            for (var i=0; i<len; i++ ) {
                arr[i] = binStr.charCodeAt(i);
            }
            callback( new Blob( [arr], {type: type || 'image/png'} ) );
         }
    });
}

 

Topics: iOS JSON