Vue + Ant Design of Vue上传文件

使用方法:

api方法

api描述默认
disabled是否可上传true
show是否显示支持的格式并切换导入模式true
buttonType上传按钮的格式“”
title上传按钮的文字上传文件
action上传接口/api/gov/upload/fileUpload
maxNum上传的最大数量1
types上传文件的格式[".doc",".docx",".pdf",".xls",".xlsx",".rar",".csv", “.zip”,".jpg",".jpeg",".gif",".png",".rar",".zip",".7z",".tar",]
isLt上传文件的大小10M
values用于编辑回显[]
params上传接口要传入的其他数据{}

ref链上的方法

获取方式描述
.fileList要保存的文件列表
.addFileList所有添加的文件列表
.handleClearList()清除保存文件列表的方法

组件中使用上传组件的时候可以封装的一些方法

实例默认ref等于myUpload

/* 
    数据处理的方法
*/
	handleRemoveFile() {
      //处理上传文件新增、删除、保存
      this.newAddFileList = []; //储存所有添加的文件列表
      this.newFileList = []; //储存所有要保存文件的列表
      this.removeFile = []; //储存所有要删除文件的列表
      //获取所有上传的文件列表
      this.newAddFileList = this.$refs.myUpload.addFileList;
      //获取所有要保存文件的列表
      this.$refs.myUpload.fileList.map((item) => {
        this.newFileList.push(item.url ? item.url : item.response.data);
      });
      //获取所有最后要删除文件的列表
      let removeFile = [];
      this.newAddFileList.map((item) => {
        if (this.newFileList.indexOf(item) == "-1") {
          removeFile.push(item);
        }
      });
      this.values.map((item) => {
        if (this.newFileList.indexOf(item) == "-1") {
          removeFile.push(item);
        }
      });
      this.removeFile = removeFile;
   },
组件的封装:
<template>
  <div class="upload-box">
    <a-upload
      name="file"
      :multiple="true"
      :action="action"
      :headers="headers"
      :file-list="fileList"
      @change="handleUploadChange"
      :beforeUpload="beforeUpload"
      :disabled="disabledBotton || disabled"
      :data="{
        ...params,
      }"
    >
      <a-button :disabled="disabledBotton || disabled" :type="buttonType">
        <a-icon type="upload" /> {{ title }}
      </a-button>
    </a-upload>
    <slot name="alert"></slot>
    <span class="type-box" v-if="show">
      <span>支持格式:</span>{{ types.join(" ") }}
    </span>
  </div>
</template>

<script>
import { getToken } from "@/utils/auth.js";
import { handleCompressImg } from "@/utils/compressImg.js";
export default {
  props: {
    disabled: {
      type: Boolean,
      default: () => {
        return true;
      },
    },
    show: {
      type: Boolean,
      default: () => {
        return true;
      },
    },
    buttonType: {
      type: String,
      default: () => {
        return "";
      },
    },
    title: {
      type: String,
      default: () => {
        return "上传文件";
      },
    },
    action: {
      type: String,
      default: () => {
        return "/api/gov/upload/fileUpload";
      },
    },
    maxNum: {
      type: Number,
      default: () => {
        return 1;
      },
    },
    types: {
      type: Array,
      default: () => {
        return [
          ".doc",
          ".docx",
          ".pdf",
          ".xls",
          ".xlsx",
          ".rar",
          ".csv",
          ".zip",
          ".jpg",
          ".jpeg",
          ".gif",
          ".png",
          ".rar",
          ".zip",
          ".7z",
          ".tar",
        ];
      },
    },
    isLt: {
      type: Number,
      default: 10,
    },
    values: {
      type: Array,
    },
    params: {
      type: null,
      default: () => {
        return {};
      },
    },
  },
  data() {
    return {
      fileList: [],
      addFileList: [],
      headers: {
        token: getToken(),
      },
      disabledBotton: false,
    };
  },
  watch: {
    values: function () {
      this.addFileList = [];
      if (this.values.length > 0) {
        let i = 0;
        this.values.map((item) => {
          i++;
          this.fileList.push({
            uid: i,
            name: i + ".文件" + item.substring(item.lastIndexOf(".")),
            status: "done",
            url: item,
          });
        });
      }
    },
  },
  created() {
    this.addFileList = [];
    if (this.values.length > 0) {
      let i = 0;
      this.values.map((item) => {
        i++;
        this.fileList.push({
          uid: i,
          name: i + ".文件" + item.substring(item.lastIndexOf(".")),
          status: "done",
          url: item,
        });
      });
    }
  },
  methods: {
    handleClearList() {
      this.fileList = [];
    },
    handleUploadChange(info) {
      if (info.file.status) {
        // this.disabledBotton = true;
        let fileList = [...info.fileList];
        if (fileList.length >= this.maxNum + 1) {
          fileList = fileList.slice(1);
        }

        //
        fileList = fileList.map((file) => {
          if (file.response) {
            file.url = file.response.url;
          }
          return file;
        });

        this.fileList = fileList;
      }
      if (info.file.status === "done") {
        if (!this.show) {
          //导入模式
          this.fileList = [];
          this.$emit("uploads");
          this.$message.success(`${info.file.response.msg}`);
        } else {
          console.log(info.file.response);
          this.addFileList.push(info.file.response.data);
          this.$message.success(`${info.file.name} 文件上传成功`);
        }
        // this.disabledBotton = false;
        // this.$emit("change", this.fileList,'up');
        // this.$emit("change", this.addFileList,'add');
      } else if (info.file.status === "error") {
        this.$message.error(`${info.file.name} 文件上传失败`);
        if (!this.show) {
          //导入模式
          this.fileList = [];
        }
      }
    },
    beforeUpload(file, fileList) {
      return new Promise((resolve, reject) => {
        let imgType = [".png", ".jpg", ".jpeg"];
        console.log("before", fileList);
        const max = this.fileList.length >= this.maxNum ? false : true;
        // const max = this.fileList.length > this.maxNum ? false : true;
        if (!max) {
          this.$message.error(`最多上传${this.maxNum}个文件`);
          reject();
        }
        // console.log(file.name.substring(file.name.lastIndexOf(".")));
        const isJpgOrPng =
          this.types.indexOf(file.name.substring(file.name.lastIndexOf("."))) !=
          "-1"
            ? true
            : false;
        if (!isJpgOrPng) {
          this.$message.error("只能上传" + this.types.join(","));
          reject();
        }

        const isLt10M = file.size / 1024 / 1024 < this.isLt;
        if (!isLt10M) {
          this.$message.error("文件不能大于" + this.isLt + "MB!");
          reject();
        }
        if (
          imgType.indexOf(file.name.substring(file.name.lastIndexOf("."))) !=
            "-1" &&
          file.size / 1024 / 1024 > 5
        ) {
          this.$message.error("图片不能大于5MB!");
          reject();
        }
        this.disabledBotton = false;
        if (
          imgType.indexOf(file.name.substring(file.name.lastIndexOf("."))) !=
          "-1"
        ) {
          handleCompressImg(file).then((res) => {
            console.log(file, res);
            res.uid = file.uid;
            resolve(res);
          });
        } else {
          resolve(file);
        }
      });
      // return isLt10M && isJpgOrPng && max;
    },
  },
};
</script>

<style lang="less" scoped>
.upload-box {
  display: inline-block;
  width: 100%;
  position: relative;
  .type-box {
    display: inline-block;
    font-size: 12px;
    line-height: 14px;
    padding-left: 60px;
    position: relative;
    padding-top: 5px;
    span {
      position: absolute;
      left: 0px;
    }
  }
}
</style>
图片压缩方法
// 压缩图片
export function handleCompressImg(file) {
  let Orientation;
  if (/^image/.test(file.type)) {
    return new Promise((resolve) => {
      // 创建一个reader
      let reader = new FileReader();
      // 将图片转成 base64 格式
      reader.readAsDataURL(file);
      // 读取成功后的回调
      reader.onloadend = function (e) {
        let img = new Image();
        let result = e.target.result;
        img.src = result;
        // 判断图片是否大于100K,是就压缩图片,反之直接上传
        // if (result.length <= (100 * 1024)) {
        //   console.log('图片小于100k') // 不对图片进行压缩操作
        //   return resolve(file)
        // } else {
        img.onload = function () {
          return resolve(dataURLtoFile(compress(img, Orientation), file.name));
        };
        // }
      };
    });
  }
}

function compress(img, Orientation) {
  // 压缩操作
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  // 瓦片canvas
  let tCanvas = document.createElement("canvas");
  let tctx = tCanvas.getContext("2d");
  let initSize = img.src.length;
  let width = img.width;
  let height = img.height;
  // 如果图片大于四百万像素,计算压缩比并将大小压至400万以下
  let ratio; //像素压缩
  if ((ratio = (width * height) / 2000000) > 1) {
    console.log("大于400万像素");
    ratio = Math.sqrt(ratio);
    width /= ratio;
    height /= ratio;
  } else {
    ratio = 1;
  }
  canvas.width = width;
  canvas.height = height;
  //        铺底色
  ctx.fillStyle = "#fff";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // 如果图片像素大于100万则使用瓦片绘制
  let count;
  if ((count = (width * height) / 1000000) > 1) {
    console.log("超过100W像素");
    count = ~~(Math.sqrt(count) + 1); // 计算要分成多少块瓦片
    //            计算每块瓦片的宽和高
    let nw = ~~(width / count);
    let nh = ~~(height / count);
    tCanvas.width = nw;
    tCanvas.height = nh;
    for (let i = 0; i < count; i++) {
      for (let j = 0; j < count; j++) {
        tctx.drawImage(
          img,
          i * nw * ratio,
          j * nh * ratio,
          nw * ratio,
          nh * ratio,
          0,
          0,
          nw,
          nh
        );
        ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
      }
    }
  } else {
    ctx.drawImage(img, 0, 0, width, height);
  }
  // 修复ios上传图片的时候 被旋转的问题
  if (Orientation !== "" && Orientation !== 1) {
    switch (Orientation) {
      case 6: // 需要顺时针(向左)90度旋转
        this.rotateImg(img, "left", canvas);
        break;
      case 8: // 需要逆时针(向右)90度旋转
        this.rotateImg(img, "right", canvas);
        break;
      case 3: // 需要180度旋转
        this.rotateImg(img, "right", canvas); // 转两次
        this.rotateImg(img, "right", canvas);
        break;
    }
  }
  // 进行最小压缩
  let ndata = canvas.toDataURL("image/jpeg", 0.4);
  console.log("压缩前:" + initSize);
  console.log("压缩后:" + ndata.length);
  console.log(
    "压缩率:" + ~~((100 * (initSize - ndata.length)) / initSize) + "%"
  );
  tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
  return ndata;
}

// base64转化成文件对象格式
function 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);
  }
  // 转换成file对象
  return new File([u8arr], filename, { type: mime });
}

自己封装的组件,有不足的地方希望各位大佬补充,可评论留言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值