图片压缩上传

224 阅读2分钟

将本地大体积图片通过前端压缩后展示并上传

步骤

file->base64->canvas->base64->blob->file

框架

vue

操作

form表单的文件类型上传和input的图片类型选择

 <template>
  <div class="imgupload">
    <form method="POST" enctype="multipart/form-data">
      <input
        type="file"
        name="file"
        accept="image/*"
        multiple="multiple"
        @change="selectFile"
      />
    </form>
    <ul>
      <li
        :style="{ height: maxHeight + 'px', width: maxHeight + 'px' }"
        v-for="(item, index) in imgList"
        :key="index"
      >
        <img
          :style="{
            height: item.targetHeight + 'px',
            width: item.targetWidth + 'px',
          }"
          :src="item.src"
          alt=""
        />
      </li>
    </ul>
  </div>
</template>

在目标图片以base64读取过程中,将图片对应的base64以Image渲染到canvas作图板上,把canvas画好的符合压缩限制的图片转成base64,再将base64转为blob类型(也可以直接转为file类但有兼容问题),blob转为file并渲染到列表上

<script>
export default {
  name: "imgupload",
  data() {
    return {
      maxHeight: 300, //图片宽高最大值
      imgList: [],  //图片展示列表
      fileList: []  //图片文件列表
    };
  },
  methods: {
    selectFile(e) { //form表单中的选择本地图片功能
      let that = this;
      const files = e.target.files;
      Object.values(files).forEach((file) => {
        var reader = new FileReader();
        reader.readAsDataURL(file);   //通过base64读取图片
        reader.onload = function(evt) {
          var img = new Image();
          img.src = evt.target.result;  //base64,图片内容
          img.onload = function() {
            //确定canvas作图宽高
            var originWidth = this.width, 
              originHeight = this.height;
            var targetWidth = originWidth,
              targetHeight = originHeight;
            if (originWidth > that.maxHeight || originHeight > that.maxHeight) { 
              if (originWidth / originHeight > 1) {
                targetWidth = that.maxHeight;
                targetHeight = Math.round(
                  (originHeight / originWidth) * that.maxHeight
                );
              } else {
                targetHeight = that.maxHeight;
                targetWidth = Math.round(
                  (originWidth / originHeight) * that.maxHeight
                );
              }
            }
            //canvas画图
            var canvas = document.createElement("canvas");
            var context = canvas.getContext("2d");
            canvas.width = targetWidth;
            canvas.height = targetHeight;
            context.clearRect(0, 0, targetWidth, targetHeight);
            context.drawImage(img, 0, 0, targetWidth, targetHeight);
            var newUrl = canvas.toDataURL("image/jpeg", 0.92);//canvas图片转base64
            //base64转blob
            var arr = newUrl.split(","),
              mime = arr[0].match(/:(.*?);/)[1],
              bstr = atob(arr[1]),
              n = bstr.length,
              u8arr = new Uint8Array(n);
            while (n--) {
              u8arr[n] = bstr.charCodeAt(n);
            }
            var blob = new Blob([u8arr], { type: mime });
            //blob转file,可设置名称和类型
            var newfile = new window.File([blob], file.name, {
              type: file.type,
            });
            that.fileList.push(newfile)//上传图片列表
            //重新读取压缩后的图片,把读取内容赋值给展示列表
            var reader = new FileReader();
            reader.readAsDataURL(newfile);
            reader.onload = function(evt) {
              that.imgList.push({
                src: evt.target.result,
                width: targetWidth,
                height: targetHeight,
              });
            };
          };
        };
      });
    },
  },
};
</script>

效果

选择文件前

选择文件之后

参考

blog.csdn.net/huangpb123/… blog.csdn.net/qq_21937107…