bootstrap fileinput 截取flies实现图片压缩

1,045 阅读2分钟

遇到的问题

诸如 tomcat、IIS、Nginx等环境,针对前台上传的附件均有期限制。当附件总内存超过临界值,就会报错,导致附件无法上传,错误如下:

image.png

此时后台压缩已经无法解决此类问题(接口都无法访问了,也就无法进入后台逻辑)
互联网产品公司中则采用的方案为前端进行附件压缩
以下我以bootstrap fileinput.js插件实现图片压缩为例为大家分享下自己的处理思路(据说此类插件有相关配置可进行压缩,奈何自己没找到😭)

逻辑解析

知识点

image.png

实现步骤

加入拦截函数

  • 找到如下图位置,加入_suoxiaoflis方法

image.png

代码:

_suoxiaoflis:function(files){
var self = this;
if (!files.length) return;
files.forEach(function (file, i) {
  if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return; 
  var reader = new FileReader();
  var imgname = file.name
  reader.onload = function () {
    var result = this.result; 
    var img = new Image(); 
    img.src = result;
    img.onload = function () {
      //声明FormData
      var form_data = new FormData();
      //开始压缩
      var data = self._compress(img); 
      //构建压缩后的FormData
      form_data.append("cunminimgfile", self._blobToFile(self._base64ToBlob(data)), imgname);
      img = null;
      self._readFilesContinue(self, form_data.getAll("cunminimgfile"))
    }
  };
  reader.readAsDataURL(file); //读取file对象
})

压缩img,将Image对象转换成base64

此类压缩的方法,网上各类型都有,本人摘的方法如下

代码:

_compress: function (img) {
    var canvas = document.createElement("canvas"); //新建画布
    var ctx = canvas.getContext('2d'); //指定二维绘图
    var initSize = img.src.length;
    var width = img.width;
    var height = img.height;

    var ratio;
    if ((ratio = width * height / 400000) > 1) { //图片大小大于40w像素则进行压缩
      ratio = Math.sqrt(ratio); //返回正平方根double值
      width /= ratio;
      height /= ratio;
    } else {
      ratio = 1;
    }
    canvas.width = width;
    canvas.height = height;
    ctx.fillStyle = "#fff"; //铺底色
    ctx.fillRect(0, 0, canvas.width, canvas.height); //绘制“被填充”矩形
    //如果图片像素大于100万则使用瓦片绘制
    var count;
    if ((count = width * height / 100000) > 1) {
      var tCanvas = document.createElement("canvas");
      var tctx = tCanvas.getContext("2d");
      count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
      //计算每块瓦片的宽和高
      var nw = ~~(width / count);
      var nh = ~~(height / count);
      tCanvas.width = nw;
      tCanvas.height = nh;
      for (var i = 0; i < count; i++) {
        for (var j = 0; j < count; j++) {
          tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
          ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
        }
      }
    } else {
      ctx.drawImage(img, 0, 0, width, height);
    }

    //进行最小压缩
    var ndata = canvas.toDataURL('image/jpeg', 0.7); //返回包含图片展示的 data URI 第二个参数标识图片质量
    return ndata;
  }

将base64转换成blob

代码:


_base64ToBlob: function (base64Data) {
  var arr = base64Data.split(','),
    fileType = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    l = bstr.length,
    u8Arr = new Uint8Array(l);
  while (l--) {
    u8Arr[l] = bstr.charCodeAt(l);
  }
  return new Blob([u8Arr], {
    type: fileType
  });
},

blob转换成file

代码:

_blobToFile: function (newBlob, fileName) {
  newBlob.lastModifiedDate = new Date();
  newBlob.name = fileName;
  return newBlob;
}
}

快速实现

将bootstrap 中原来的 fileinput.js替换成如下脚本fileinputYaSuo.js即可 网盘链接:pan.baidu.com/s/1sw0PE2m1… 密码:9clp