欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端图片上传总结

程序员文章站 2022-04-06 11:40:17
...

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

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

<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;
  }
}

 

相关标签: input