前端图片上传总结

前端经常有图片上传的需求,这里做一下总结。

对于前端来说,单纯的上传图片还是很简单的,

<input type=“file”/>

就可以搞定,你可以增加size属性控制用户一次性能选几张。

采坑开始:

1、部分安卓手机微信直接进图库选取,不能拍照

经排查,安卓微信只认accept="image/*",其他的都不好使,加上这个就好了。。。

2、往往需求不会那么简单。

图片选择后,base64传后台,前端展示用户选取的图片,就需要通过FileReader读取文件,获得base64.

以vue为例代码:

input(class="upload-img", type="file", @change="uploadImg", name="uploadImg", size="1",accept="image/*")

uploadImg(event) {
   const target = event.target
   if (target && target.files.length > 0) {
      utils.loading('上传中')
      const type = target.files[0].type
      if (type === "image/png" || type === "image/jpeg") {
         utils.getBase64(target, (info) => {
         if (info && info.result) {
            this.src = info.result
            this.base64=info.base64
            this.getAnswer(this.base64)
           }
       })
      } else {
          this.toast('仅支持png、jpg格式');
       }
   }
},
function getBase64(node, callback) {
  let files = node.files;
  let file = files[0];
  let reader = new FileReader();
  reader.onload = () => {
    let fileInfo = {
      name: file.name,
      type: file.type,
      size: file.size,
      base64: reader.result.split(',')[1],
      result: reader.result
    };
    callback && callback(fileInfo)
  }
  reader.readAsDataURL(file);
}

3、到这里只是理想的情况,然而事实不是这样滴,部分ios手机拍照后,拿到的base64图片是横向的,这就头疼了,我们需要判断一下进行旋转。

这里用到了exif-js,修改getBase64代码

function getBase64(node, callback) {
  let files = node.files;
  let file = files[0];
  let reader = new FileReader();
  reader.onload = (e) => {
    let fileInfo = {
      name: file.name,
      type: file.type,
      size: file.size,
      base64: reader.result.split(',')[1], //reader.result.split(',')[1],
      result: reader.result
    };
    getPhotoOrientation(file, function (orientation) {
      if (orientation != '' && orientation != 1) {
        var image = new Image();
        image.onload = function() {
          var expectWidth = this.naturalWidth;
          var expectHeight = this.naturalHeight;

          if (this.naturalWidth > this.naturalHeight && this.naturalWidth > 800) {
            expectWidth = 800;
            expectHeight = expectWidth * this.naturalHeight / this.naturalWidth;
          } else if (this.naturalHeight > this.naturalWidth && this.naturalHeight > 1200) {
            expectHeight = 1200;
            expectWidth = expectHeight * this.naturalWidth / this.naturalHeight;
          }
          var canvas = document.createElement("canvas");
          var ctx = canvas.getContext("2d");
          canvas.width = expectWidth;
          canvas.height = expectHeight;
          ctx.drawImage(image, 0, 0, expectWidth, expectHeight);
          var base64 = null;
          switch (orientation) {
            case 6://需要顺时针(向左)90度旋转
              rotateImg(this, 'left', canvas);
              break;
            case 8://需要逆时针(向右)90度旋转
              rotateImg(this, 'right', canvas);
              break;
            case 3://需要180度旋转
              rotateImg(this, 'right', canvas);//转两次
              rotateImg(this, 'right', canvas);
              break;
          }
          base64 = canvas.toDataURL("image/jpeg")
          console.log("1"+base64);
          console.log("2"+base64.split(',')[1])
          fileInfo.base64 = base64.split(',')[1]
          fileInfo.result = base64
          callback && callback(fileInfo)
        }
        image.src = reader.result;
      } else {
        callback && callback(fileInfo)
      }
    })
  }
  reader.readAsDataURL(file);

}

function getPhotoOrientation(file, callback) {
  EXIF.getData(file, function () {
    var orient = ''
    orient = EXIF.getTag(this, 'Orientation')
    callback && callback(orient)
  });
}

// 对图片旋转处理
function rotateImg(img, direction, canvas) {
  //最小与最大旋转方向,图片旋转4次后回到原方向
  var min_step = 0;
  var max_step = 3;
  //var img = document.getElementById(pid);
  if (img == null)return;
  //img的高度和宽度不能在img元素隐藏后获取,否则会出错
  var height = img.height;
  var width = img.width;
  var step = 2;
  if (step == null) {
    step = min_step;
  }
  if (direction == 'right') {
    step++;
    //旋转到原位置,即超过最大值
    step > max_step && (step = min_step);
  } else {
    step--;
    step < min_step && (step = max_step);
  }

  //旋转角度以弧度值为参数
  var degree = step * 90 * Math.PI / 180;
  var ctx = canvas.getContext('2d');
  switch (step) {
    case 0:
      canvas.width = width;
      canvas.height = height;
      ctx.drawImage(img, 0, 0);
      break;
    case 1:
      canvas.width = height;
      canvas.height = width;
      ctx.rotate(degree);
      ctx.drawImage(img, 0, -height);
      break;
    case 2:
      canvas.width = width;
      canvas.height = height;
      ctx.rotate(degree);
      ctx.drawImage(img, -width, -height);
      break;
    case 3:
      canvas.width = height;
      canvas.height = width;
      ctx.rotate(degree);
      ctx.drawImage(img, -width, 0);
      break;
  }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值