antdv的Upload组件上传功能

1,135 阅读1分钟

个人纪录方便自己以后查看 大佬请忽略 本文章出自 ykCoder搬砖方便自己阅读

功能实现原理

在上传图片前获取该图片的文件流(beforeUpload中获取),对这个文件流进行压缩操作,再将压缩后的文件流传过去(resolve(newFile)),最后进行自定义的上传请求(customRequest中实现)。

图片预览方式

前端本地图片的预览则可以选择blob或者base64的方式,本文推荐使用blob方式来预览图片的文件流。

部分代码

html

<template>
  <div>
    <a-spin :spinning="isShowSpinning">
      <img
        v-if="imageUrl"
        :src="data:imageUrl"
        style="width: 200px; height: 200px; margin-right: 10px"
      />
      <a-upload
        accept="image/*"
        :beforeUpload="beforeImageUpload"
        :customRequest="customImageRequest"
      >
        <a-button type="primary"> <a-icon type="upload" />上传 </a-button>
      </a-upload>
    </a-spin>
  </div>
</template>

api

import request from '@/utils/request'
const api = {
    uplodBackName: '/biz/uplodBackName'
}
export function getUplodBackName (parameter) {
  return request({
    url: api.uplodBackName,
    method: 'post',
    // 传输文件流需要单独设置请求头
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    data: parameter
  })
}

js

<script>
import { getUplodBackName } from "@/api/biz/manage";
export default {
  components: {},
  data() {
    return {
      imageUrl: "",
      isShowSpinning: false,
    };
  },
  methods: {
    // 上传图片前的钩子函数
    beforeImageUpload(file, fileList) {
      return new Promise(async (resolve, reject) => {
        if (!file.type.includes("image")) {
          this.$message.warning("请上传图片");
          reject(new Error("请上传图片"));
          return;
        }
        this.isShowSpinning = true;
        const newFile = await this.compressImg(file);
        resolve(newFile);
      });
    },
    // 自定义的上传请求
    customImageRequest(info) {
      const { file } = info;
      // blob方式预览图片
      this.imageUrl = window.URL.createObjectURL(file);
      // 组装数据
      const formData = new FormData();
      formData.append("files", file);
      // 发送请求
      getUplodBackName(formData)
        .then((res) => {
          this.$message.success("上传成功");
        })
        .catch(() => {
          this.$message.warning("上传失败");
        })
        .finally(() => {
          this.isShowSpinning = false;
        });
    },
    // base64转码(压缩完成后的图片为base64编码,这个方法可以将base64编码转回file文件)
    dataURLtoFile(dataurl, filename) {
      var arr = dataurl.split(",");
      var mime = arr[0].match(/:(.*?);/)[1];
      var bstr = atob(arr[1]);
      var n = bstr.length;
      var u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, { type: mime });
    },
    // 图片压缩函数
    compressImg(file) {
      const that = this;
      var files;
      var fileSize = parseFloat(parseInt(file["size"]) / 1024 / 1024).toFixed(
        2
      );
      var read = new FileReader();
      read.readAsDataURL(file);
      return new Promise(function (resolve, reject) {
        read.onload = function (e) {
          var img = new Image();
          img.src = e.target.result;
          img.onload = function () {
            // 默认按比例压缩
            var w = this.width;
            var h = this.height;
            // 生成canvas
            var canvas = document.createElement("canvas");
            var ctx = canvas.getContext("2d");
            var base64;
            // 创建属性节点
            canvas.setAttribute("width", w);
            canvas.setAttribute("height", h);
            ctx.drawImage(this, 0, 0, w, h);
            if (fileSize < 1) {
              // 如果图片小于一兆 那么压缩0.5
              base64 = canvas.toDataURL(file["type"], 0.5);
            } else if (fileSize > 1 && fileSize < 2) {
              // 如果图片大于1M并且小于2M 那么压缩0.5
              base64 = canvas.toDataURL(file["type"], 0.5);
            } else {
              // 如果图片超过2m 那么压缩0.2
              base64 = canvas.toDataURL(file["type"], 0.2);
            }
            // 回调函数返回file的值(将base64编码转成file)
            files = that.dataURLtoFile(base64, file.name); // 如果后台接收类型为base64的话这一步可以省略
            resolve(files);
          };
        };
      });
    },
  },
};
</script>