zoukankan      html  css  js  c++  java
  • vue头像上传与文件压缩

    工作中遇到的问题记录:vue开发头像上传组件,后端提供接口,需求为可相册上传,可相机拍摄上传,文件大小限制为2M

    需求点分析

    1. 移动端调用相册/摄像头实现拍照
    2. 图片压缩,当前高像素的相机拍出来的图片都有个4-5m大小,超出了限定的2m
    3. 图片上传

    第一点:移动端调用相册/摄像头实现拍照

    这就比较简单了,H5的标签足已经能满足我们的要求了,我们要做的只是让它更美观一点

            <div class="yb-headSet-but">
              <div class="btn-box">
                <input type="file" accept="image/*" @change="uploadImg" class="fromAlbum">   //设置input opacity为0,定位覆盖a标签,a标签设置为设计稿的按钮样式
                <a href="" class="weui-but">从相册选一张</a>
              </div>
              <div class="btn-box">
                <a href="" class="weui-but">拍一张照片</a>
                <input type="file" accept="image/*" @change="uploadImg" capture="camera" class="fromCamera">    //两者区别:capture="camera" 可直接调用摄像头
              </div>
            </div>         
    

    第二点:图片压缩

    利用的是canvas的drawImage 和 toDataURL的api,具体代码是复制的 https://www.jianshu.com/p/4587312d2f44
    修改了几个大佬笔误的地方

    imgResize(file, callback) {
          var _this = this;
          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 = {
                 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 = h / multiple;
              } else {
                // 如果图片尺寸小于最大限制,则不压缩直接上传
                return callback(file);
              }
              var canvas = document.createElement("canvas");
              var ctx = canvas.getContext("2d");
              if (window.navigator.userAgent.indexOf("iPhone") > 0) {
                canvas.width = resizeH;
                canvas.height = resizeW;
                ctx.rotate(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/" + _this.fileType, maxSize.level);
              _this.convertBlob(window.atob(base64.split(",")[1]), callback);
            };
          };
          fileReader.readAsDataURL(file);
        },
    

    图片上传

    使用canvas.toDataURL获得的是base64格式,上传时需要转换成Blob二进制格式,使用formData提交

    //Blob对象生成
    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/" + this.fileType });
          } 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/" + this.fileType);
            }
          }
          callback(blob);
        },
    //提交函数
    postImg(file) {
          let image = new FormData();
          image.append("file", file, this.random_string(12) + '.' + this.fileType);
          console.log(image);
          setHead(image).then(res => {
            this.$indicator.close();
            if (res.Success) {
              let newPath = res.photoPath +'?t=' + this.random_string(12);
              this.$store.commit("UPDATE_BASEINFO", { photoPath: newPath });
              this.picValue = newPath;
              this.$messagebox.alert(res.Message);
            } else {
              this.$messagebox.alert(res.Message);
            }
          });
        },
    

    注意注意 这里有个巨大的坑。。。。。

    这个坑是这样的,我使用压缩过的Blob格式提交后台时,返回提示文件格式不正确,不属于jpeg、jpg等,这我就纳闷了,我上传的formData里面写明了文件格式了啊;
    后来经过简书大佬 一斤代码 老大的帮助,老大测试后说出了问题所在:那就是 FormData.append('file', file),如果只有两个参数,(第三个参数是文件名)的情况下,默认fileName=“blob”,这样上次至后台,如果后台未做其他处理的话,就会出现报错的情况,后来就添加了随机文件名,完整代码如下

    <template>
      <div class="yb-page">
        <div class="yb-page-inner">
          <div class="yb-headSetting">
            <div class="yb-headSet-img">
              <img :src="picValue" alt="" onerror="this.src='https://ixxxxxx.com/we/tmpls/t9000/img/account/blackHead@2x.png'">
            </div>
            <div class="yb-headSet-but">
              <div class="btn-box">
                <input type="file" ref="avatarInput" accept="image/*" @change="uploadImg" class="fromAlbum">
                <a href="" class="weui-but">从相册选一张</a>
              </div>
              <div class="btn-box">
                <a href="" class="weui-but">拍一张照片</a>
                <input type="file" accept="image/*" @change="uploadImg" capture="camera" class="fromCamera">
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
    <script>
    import { setHead } from "@/api/user";
    export default {
      data() {
        return {
          picValue: this.$store.getters.baseInfo.photoPath,
          file: null,
          fileType: ''
        };
      },
      methods: {
        uploadImg(e) {
          if (e.target.value == "") {
            return;
          }
          this.$indicator.open();
          let files = e.target.files || e.dataTransfer.files;
          if (!files.length) return;
          this.file = files[0];
          this.fileType = this.file.type.split('/')[1];
          this.imgResize(files[0], this.postImg);
        },
        postImg(file) {
          let image = new FormData();
          image.append("file", file, this.random_string(12) + '.' + this.fileType);
          console.log(image);
          setHead(image).then(res => {
            this.$indicator.close();
            if (res.Success) {
              let newPath = res.photoPath +'?t=' + this.random_string(12);
              this.$store.commit("UPDATE_BASEINFO", { photoPath: newPath });
              this.picValue = newPath;
              this.$messagebox.alert(res.Message);
            } else {
              this.$messagebox.alert(res.Message);
            }
          });
        },
        imgResize(file, callback) {
          var _this = this;
          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 = {
                 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 = h / multiple;
              } else {
                // 如果图片尺寸小于最大限制,则不压缩直接上传
                return callback(file);
              }
              var canvas = document.createElement("canvas");
              var ctx = canvas.getContext("2d");
              if (window.navigator.userAgent.indexOf("iPhone") > 0) {
                canvas.width = resizeH;
                canvas.height = resizeW;
                ctx.rotate(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/" + _this.fileType, maxSize.level);
              _this.convertBlob(window.atob(base64.split(",")[1]), callback);
            };
          };
          fileReader.readAsDataURL(file);
        },
        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/" + this.fileType });
          } 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/" + this.fileType);
            }
          }
          callback(blob);
        },
        random_string(len) {
          len = len || 32;
          var chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
          var maxPos = chars.length;
          var pwd = "";
          for (var i = 0; i < len; i++) {
            pwd += chars.charAt(Math.floor(Math.random() * maxPos));
          }
          return pwd;
        }
      }
    };
    </script>
    
    
  • 相关阅读:
    python给邮箱发送消息
    shell 的echo和 printf
    shell 基本运算符
    shell傳遞參數
    shell變量和數組
    pycharm的放大和缩小字体的显示 和ubunt的截圖工具使用 ubuntu上安装qq微信等工具
    flask的g对象
    mysqlcilent的安装
    Ubuntu安装 和 python开发
    使用python来建立http服务
  • 原文地址:https://www.cnblogs.com/milo-wjh/p/9260276.html
Copyright © 2011-2022 走看看