美文网首页HTML5HTML5 CanvasHTML5
使用HTML5实现图片压缩上传功能

使用HTML5实现图片压缩上传功能

作者: 山不转谁转 | 来源:发表于2017-04-20 16:33 被阅读2226次
    实现流程:
    • 获取<input type="file">上传的文件;
    • 使用FileReader读取图片,并新建一个Image对象将FileReader读取的图片数据放进去;
    • 使用canvas将Image对象等比缩放并写入到画布中,保存为base64格式的数据(这里使用的是FormData对象上传,其实这里已经可以直接将base64的数据通过ajax使用post方法上传到服务器,即可避免下面两个步骤);
    • 新建一个Blob对象将base64数据放入;
    • 使用FormData对象上传到第三方云储存服务器;
    使用HTML原生<input type="file">上传图片,下面是踩的一些小坑:
    • accept设定上传文件的类型,这里直接用image/*,不指定具体的后缀名,否则部分安卓手机下无法上传图片;
    • 添加multiple属性可选取多张图片(本例只做选取单张图片);
    • capture="camera"属性可以调用摄像头(添加此属性在iPhone下会直接调用摄像头,而不会读取相册;且目前安卓和ios设备使用accept="image/*"均可选择使用摄像头拍照还是使用相册的图片,所以该属性可以忽略)。
    <input id="imgUpload" type="file" onchange="addPic" accept="image/*" />
    
    当input文件触发change事件后获取上传的文件
    function addPic(e){
      if (typeof FileReader === 'undefined') {
        return alert('你的浏览器不支持上传图片哟!');
      }
      var files = e.target.files || e.dataTransfer.files;
      if(files.length > 0){
        imgResize(file[0], callback);
      }
    }
    
    使用FileReader获取图片数据,并使用canvas压缩
    • ios手机拍照会旋转90度,这里必须判断是否ios手机做出相应处理后再上传
    function imgResize(file, callback){
      var fileReader = new FileReader();
      fileReader.onload = function(){
        var IMG = new Image();
        IMG.src = this.result;
        IMG.onload = function(){
          var w = this.naturalWidth, h = this.naturalHeight, resizeW = 0, resizeH = 0;
          // maxSize 是压缩的设置,设置图片的最大宽度和最大高度,等比缩放,level是报错的质量,数值越小质量越低
          var maxSize = {
            width: 500,
            height: 500,
            level: 0.6
          };
          if(w > maxSize.width || h > maxSize.height){
            var multiple = Math.max(w / maxSize.width, h / maxSize.height);
            resizeW = w / multiple;
            resizeH = w / multiple;
          } else {
            // 如果图片尺寸小于最大限制,则不压缩直接上传
            return callback(file)
          }
          var canvas = document.createElement('canvas'),
          ctx = canvas.getContext('2d');
          if(window.navigator.userAgent.indexOf('iPhone') > 0){
            canvas.width = resizeH;
            canvas.height = resizeW;
            ctx.rorate(90 * Math.PI / 180);
            ctx.drawImage(IMG, 0, -resizeH, resizeW, resizeH);
          }else{
            canvas.width = resizeW;
            canvas.height = resizeH;
            ctx.drawImage(IMG, 0, 0, resizeW, resizeH);
          }
          var base64 = canvas.toDataURL('image/jpeg', maxSize.level);
          convertBlob(window.atob(base64.split(',')[1]), callback);
        }
      };
      fileReader.readAsDataURL(file);
    }
    
    将base64的数据转换成一个Blob对象
    • 安卓手机不支持Blob构造方法
    function convertBlob(base64, callback){
      var buffer = new ArrayBuffer(base64.length);
      var ubuffer = new Uint8Array(buffer);
      for (var i = 0; i < base64.length; i++) {
        ubuffer[i] = base64.charCodeAt(i)
      }
      var blob;
      try {
        blob = new Blob([buffer], {type: 'image/jpg'});
      } catch (e) {
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
        if(e.name === 'TypeError' && window.BlobBuilder){
          var blobBuilder = new BlobBuilder();
          blobBuilder.append(buffer);
          blob = blobBuilder.getBlob('image/jpg');
        }
      }
      callback(blob)
    }
    
    使用HTML5的FormData对象上传数据
    function callback(fileResize){
      var data = new FormData();
      data.append('file', fileResize);
      var config = {
        headers: {'Content-Types': 'multipart/form-data'}
      };
      // 这里用的es6语法发起请求,可以无视
      axios.post(url, data, config).then().catch(e){}
    }
    

    相关文章

      网友评论

      • 隐居青楼:这个怎么用呢?貌似没什么效果啊
      • 37cccd33f206:刚好最近在做这个,感谢作者分享~
        imgResize函数里似乎有个小笔误:
        resizeH = w / multiple;
        是不是应该改成
        resizeH = h / multiple;
        bb28daae5feb:还有一个
        data.append('file', fileResize); 要添加第三个参数 文件名;
        data.append('file', fileResize, test.jpg); 防止默认文件名为blob 在后端会报错!!!
        这个问题坑的我哟, 还好友简书大佬 一斤代码 帮我!!
        NAME宝顺:还有rorate写错了

      本文标题:使用HTML5实现图片压缩上传功能

      本文链接:https://www.haomeiwen.com/subject/pwslzttx.html