首页 > 建站教程 > JS、jQ、TS >  前端实现图片压缩上传(兼容ios10系统)正文

前端实现图片压缩上传(兼容ios10系统)

近期需要做一个需求,关于前端获取图片后压缩,再上传给后台服务器或者上传至oss后将路径传给后台服务器,压缩的时候发现在ios10及以下的系统是无效的,经查证,这是由于使用canvas的 HTMLCanvasElement.toBlob() 方法创造blob对象的时候,ios10及以下系统无法调用。

答案:

1. 实现前端压缩图片并上传

(1)HTML:图片预览盒子&input上传控件
<div id="uploader">
     <!-- 展示预览图片 -->
     <!-- <div class="img_show"></div> -->
     <!-- 图片上传 -->
     <div id="fileInput" class="img_uploader">
         <input id="imgUpload" type="file" name="imgs" accept="image/*">
     </div>
</div>
(2)图片上传及压缩
// 表单上传的formdata对象
var fd = new FormData();
// 用于压缩图片的canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
var file = null;       // 用户上传的图片对象
 
/* 点击input上传图片 */
$("#fileupload").on('change', function (e) {  
    file = event.target.files[0];
    // 图片预览,加载base64图片
    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]);
 
    // base64地址图片加载完毕后,绘制canvas压缩图片
    img.onload = function () {
        // 图片原始尺寸
        var originWidth = this.width;
        var originHeight = this.height;
        // 最大尺寸限制
        var maxWidth = 800, maxHeight = 800;
        // 目标尺寸
        var targetWidth = originWidth, targetHeight = originHeight;
        // 图片尺寸超过400x400的限制
        if (originWidth > maxWidth || originHeight > maxHeight) {
             if (originWidth / originHeight > maxWidth / maxHeight) {
                 // 更宽,按照宽度限定尺寸
                 targetWidth = maxWidth;
                 targetHeight = Math.round(maxWidth * (originHeight / originWidth));
             } else {
                 targetHeight = maxHeight;
                 targetWidth = Math.round(maxHeight * (originWidth / originHeight));
             }
        }
        // canvas对图片进行缩放
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        // 清除画布
        ctx.clearRect(0, 0, targetWidth, targetHeight);
        // 图片压缩
        ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
        // 当canvas对象的原型中没有toBlob方法的时候,手动添加该方法
        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转为blob并上传
        canvas.toBlob(function (blob) {
            fd.append('pic', blob)
        }, file.type||'image/png');
   };
})
(3)上传图片
fd.append("uid", uids);
$.ajax({
     type: "post",
     url: baseUrl + "xxxx/xxxxx",
     data: fd,
     dataType: "json",
     processData: false,  // processData和contentType需设置为false
     contentType: false,
     async: false,
     success: function (res) {
         // ... ...       
     }
})
2. 兼容ios10系统
// 当canvas对象的原型中没有toBlob方法的时候,手动添加该方法
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'} ) );
         }
    });
}