antd 上传文件

<template>
  <!-- 主视图 -->
  <div class="upload-view">
    <!--  a-upload-dragger 组件 -->
    <a-upload-dragger
      v-if="isDragger"
      :accept="accept"
      :multiple="multiple"
      :disabled="disabled"
      :showUploadList="showUploadList"
      :fileList="fileList"
      :beforeUpload="beforeUpload"
      :customRequest="customRequest"
      :remove="remove"
      :listType="listType"
      @download="download"
    >
      <!-- 自定义上传组件 -->
      <slot name="up-slot" :disabled="disabled">
        <!-- icon -->
        <p class="ant-upload-drag-icon">
          <!-- 上传 icon -->
          <slot name="up-icon">
            <a-icon type="inbox"/>
          </slot>
        </p>
        <!-- 文案 -->
        <p class="ant-upload-text">
          <!-- 上传文案 -->
          <slot name="up-title">点击或拖拽文件到此区域上传</slot>
        </p>
        <!-- 提示文案 -->
        <p class="ant-upload-hint">
          <!-- 上传提示文案 -->
          <slot name="up-hint">支持单次或批量上传</slot>
        </p>
      </slot>
    </a-upload-dragger>
    <!--  a-upload 组件 -->
    <a-upload
      v-else
      :accept="accept"
      :multiple="multiple"
      :disabled="disabled"
      :showUploadList="showUploadList"
      :fileList="fileList"
      :beforeUpload="beforeUpload"
      :customRequest="customRequest"
      :remove="remove"
      :listType="listType"
      @download="download"
      @preview="handlePreview"
    >
              <!-- {{disabled}}--3-{{listType}} -->
      <!-- 自定义上传组件 -->
      <!-- <slot name="up-slot">
        <template v-if="listType === 'text'">
          <a-button :disabled="disabled">
            <slot name="up-icon">
              <a-icon type="upload"/>
            </slot>
            <slot name="up-title">上传文件</slot>
          </a-button>
        </template>
        <template v-else>

          <a-icon type="plus"/>
          <div class="ant-upload-text">
            上传
          </div>
        </template>
      </slot> -->
        <!-- <a-icon type="plus"/>
          <div class="ant-upload-text">
            上传
          </div> -->

       <div>
        <a-icon type="plus" />
        <div class="ant-upload-text">
          上传
        </div>
      </div>
    </a-upload>

    <a-modal :visible="previewVisible" :footer="null" @cancel="previewVisible = false" :centered="true">
      <img alt="img" style="width: 100%" :src="previewImage"/>
    </a-modal>
  </div>
</template>

<script>
  import { uploadCustom, downloadCustom } from './upload.js'

  export default {
    props: {

      // =============================== 原生属性 - a-upload 自带属性扩展 ========

      // 启用拖拽上传
      // (false: 使用 a-upload 组件,true: 使用 a-upload-dragger 组件)
      isDragger: {
        type: Boolean,
        default: () => false
      },
      // 接受上传的文件类型
      // 参考地址:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers
      // 音频:'audio/*'
      // 视频:'video/*'
      // 图片:'image/*'
      // 特殊匹配自行传入正则
      accept: {
        type: String,
        default: () => undefined
      },
      listType: {
        type: String,
        default: 'text',
        validator: function (value) {
          // 这个值必须匹配下列字符串中的一个
          return ['text', 'picture', 'picture-card'].indexOf(value) !== -1
        }
      },
      // 已经上传的文件列表(受控)
      // 文件案例:
      // [{
      //   uid: '必带,文件唯一标识',
      //   name: '必带,文件名',
      //   // uploading(上传中)、done(上传成功)、error(上传失败)、removed(移除,点击组件自带的删除按钮会被设置为移除状态,通常只需要前三种状态)
      //   status: '必带,上传状态',
      //   url: '可选,有链接可以进行跳转',
      //   dupid: '可选,防止重复文件标识(file.lastModified)',
      //   upid: '可选,本轮上传唯一标识,提交服务器时可剔除',
      //   如果需要什么其他字段或辅助字段,可以自行添加,或者通过拦截 beforeUploadPro 拿到 fileJson 自行附带
      // }]
      fileList: {
        type: Array,
        default: () => []
      },
      // 是否展示上传列表
      showUploadList: {
        type: [Boolean, Object],
        default: () => ({
          showDownloadIcon: true,
          showPreviewIcon: true
        })
      },
      // 是否支持多选文件,ie10+ 支持。开启后按住 ctrl 可选择多个文件。
      multiple: {
        type: Boolean,
        default: () => true
      },
      // 是否禁用
      disabled: {
        type: Boolean,
        default: () => false
      },
      // 准备上传,回调钩子,若返回 false 则停止上传
      // 类型:(file, fileList, fileJson) => boolean || Promise
      beforeUploadPro: {
        type: Function,
        default: undefined
      },
      // 自定义上传,回调钩子,可以自定义自己的上传实现,
      // 类型:(data, fileJson, (isSuccess) => {}) => {}
      customRequestPro: {
        type: Function,
        default: undefined
      },
      // 点击移除文件时的回调,返回值为 false 时不移除
      // 类型:(file) => boolean || Promise
      removePro: {
        type: Function,
        default: undefined
      },
      // 点击下载文件时的回调
      downloadPro: {
        type: Function,
        default: undefined
      },

      previewEnabled: {
        type: Boolean,
        default: false
      },
      // =============================== 公用检测 - 文件检测 ========

      // 文件检测模式:
      // 0 -> 不检测
      // 1 -> 本次选择的所有文件,检测失败的移除,成功的上传
      // 2 -> 本次选择的所有文件,有一个检测失败,全部移除
      fileCheckMode: {
        type: Number,
        default: () => 2
      },

      // =============================== 公用检测 - 检测错误控制 ========

      // 每轮文件上传检测错误抛出模式:
      // 0 -> 不限制,有多少错误正常抛出,可以通过每轮的 uploadId 自行判断重复问题
      // 1 -> 本轮检测错误只会抛出一次,如果本轮有多次错误,只会抛出第一次的错误,后续错误都不会在抛出
      // 每轮:也就是每次点击上传按钮选择文件后确定上传算一轮,也是本次提交(单选多选都一样)
      errorMode: {
        type: Number,
        default: () => 1
      },
      // 错误唯一标识(uploadId)存放(只在 errorMode 模式为 1 时生效)
      errorUploadIds: {
        type: Array,
        default: () => []
      },

      // =============================== 公用检测 - 文件数量限制 ========

      // 上传文件数量限制:0 -> 不限制,随便传
      fileNumber: {
        type: Number,
        default: () => 6
      },
      // 上传文件数量限制检测失败提示
      fileNumberError: {
        type: String,
        default: () => '已超出上传文件数量限制, 最多可上传6个文件'
      },
      // 上传文件数量限制失败提示,实现这个将不使用 fileRepeatError
      // 类型:(file, fileList, uploadId) => {}
      // uploadId:本次上传操作唯一ID,多选文件模式可通过该唯一ID只显示一次错误
      fileNumberErrorPro: {
        type: Function,
        default: undefined
      },

      // =============================== 公用检测 - 文件重复 ========

      // 文件重复检测模式:
      // 0 -> 允许重复
      // 1 -> 禁止重复文件(多选模式:本次选择的所有文件,重复文件移除,不重复文件上传)
      // 2 -> 禁止重复文件(多选模式:本次选择的所有文件,有一个存在重复,全部移除)
      fileRepeatMode: {
        type: Number,
        default: () => 2
      },
      // 文件重复检测失败提示
      fileRepeatError: {
        type: String,
        default: () => '不能重复导入文件'
      },
      // 文件重复检测失败提示,实现这个将不使用 fileRepeatError
      // 类型:(file, fileList, uploadId, repeatFiles) => {}
      // uploadId:本次上传操作唯一ID,多选文件模式可通过该唯一ID只显示一次错误
      // repeatFiles: 重复文件列表
      fileRepeatErrorPro: {
        type: Function,
        default: undefined
      },

      // =============================== 公用检测 - 文件大小 ========

      // 文件大小检测模式(单位 kb):
      // 0 -> 关闭
      // 1 -> 小于
      // 2 -> 大于
      // 3 -> 等于
      // 11 -> 小于或等于
      // 22 -> 大于或等于
      kbCompareMode: {
        type: Number,
        default: () => 11
      },
      // 文件大小(单位 kb)
      kbCompareSize: {
        type: Number,
        default: () => 102400
      },
      // 文件大小检测失败提示
      kbCompareError: {
        type: String,
        default: () => '文件大小超限,最大100M'
      },
      // 文件大小检测失败提示回调,实现这个将不使用 kbCompareError
      // 类型:(file, fileList, uploadId) => {}
      // uploadId:本次上传操作唯一ID,多选文件模式可通过该唯一ID只显示一次错误
      kbCompareErrorPro: {
        type: Function,
        default: undefined
      },

      // =============================== 图片检查 - 宽高限制 ========

      // 图片宽高检测模式(单位 px):
      // 0 -> 关闭
      // 1 -> 小于
      // 2 -> 大于
      // 3 -> 等于
      // 11 -> 小于或等于
      // 22 -> 大于或等于
      imgSizeMode: {
        type: Number,
        default: () => 0
      },
      // 图片宽度(单位 px)
      imgSizeWidth: {
        type: Number,
        default: () => 0
      },
      // 图片高度(单位 px)
      imgSizeHeight: {
        type: Number,
        default: () => 0
      },
      // 图片宽高检测失败提示
      imgSizeError: {
        type: String,
        default: () => '图片宽高与设定宽高不匹配'
      },
      // 图片宽高检测失败提示回调,实现这个将不使用 imgSizeError
      // 类型:(file, fileList, uploadId) => {}
      // uploadId:本次上传操作唯一ID,多选文件模式可通过该唯一ID只显示一次错误
      imgSizeErrorPro: {
        type: Function,
        default: undefined
      },

      // =============================== 图片检查 - 比例限制 ========

      // 图片比例检测模式(单位 px):
      // 0 -> 关闭
      // 1 -> 开启
      imgScaleMode: {
        type: Number,
        default: () => 0
      },
      // 图片宽度比例
      imgScaleWidth: {
        type: Number,
        default: () => 0
      },
      // 图片高度比例
      imgScaleHeight: {
        type: Number,
        default: () => 0
      },
      // 图片比例检测失败提示
      imgScaleError: {
        type: String,
        default: () => '图片比例与设定比例不匹配'
      },
      // 图片比例检测失败提示回调,实现这个将不使用 imgScaleError
      // 类型:(file, fileList, uploadId) => {}
      // uploadId:本次上传操作唯一ID,多选文件模式可通过该唯一ID只显示一次错误
      imgScaleErrorPro: {
        type: Function,
        default: undefined
      },

      // =============================== 视频检查 - 宽高限制 ========

      // 图片宽高检测模式(单位 px):
      // 0 -> 关闭
      // 1 -> 小于
      // 2 -> 大于
      // 3 -> 等于
      // 11 -> 小于或等于
      // 22 -> 大于或等于
      videSizeMode: {
        type: Number,
        default: () => 0
      },
      // 图片宽度(单位 px)
      videSizeWidth: {
        type: Number,
        default: () => 0
      },
      // 图片高度(单位 px)
      videSizeHeight: {
        type: Number,
        default: () => 0
      },
      // 图片宽高检测失败提示
      videSizeError: {
        type: String,
        default: () => '视频宽高与设定宽高不匹配'
      },
      // 图片宽高检测失败提示回调,实现这个将不使用 videSizeError
      // 类型:(file, fileList, uploadId) => {}
      // uploadId:本次上传操作唯一ID,多选文件模式可通过该唯一ID只显示一次错误
      videSizeErrorPro: {
        type: Function,
        default: undefined
      },

      // =============================== 图片检查 - 比例限制 ========

      // 图片比例检测模式(单位 px):
      // 0 -> 关闭
      // 1 -> 开启
      videScaleMode: {
        type: Number,
        default: () => 0
      },
      // 图片宽度比例
      videScaleWidth: {
        type: Number,
        default: () => 0
      },
      // 图片高度比例
      videScaleHeight: {
        type: Number,
        default: () => 0
      },
      // 图片比例检测失败提示
      videScaleError: {
        type: String,
        default: () => '视频比例与设定比例不匹配'
      },
      // 图片比例检测失败提示回调,实现这个将不使用 videScaleError
      // 类型:(file, fileList, uploadId) => {}
      // uploadId:本次上传操作唯一ID,多选文件模式可通过该唯一ID只显示一次错误
      videScaleErrorPro: {
        type: Function,
        default: undefined
      },

      // =============================== 自定义属性存放 ========

      // 如果自定义上传写在本组件内部,回调结果自行决定,外层通过 fileJson.status 判断成功失败即可
      // 例如:(fileJson, err || res) => {}
      uploadResult: {
        type: Function,
        default: undefined
      },
      // 图片预览方式
      // modal -> modal弹窗
      // fullscreen -> 全屏
      previewMode: {
        type: String,
        default: () => 'modal'
      }
    },
    data () {
      return {
        previewVisible: false,
        previewImage: ''
      }
    },
    methods: {
      handlePreview (file) {
        if (this.previewEnabled) {
          if (this.previewMode === 'modal') {
            this.previewImage = file.url
            this.previewVisible = true
          }
          if (this.previewMode === 'fullscreen') {
            const imageList = this.fileList.map(item => {
              return item.url
            })
            const currentIndex = imageList.findIndex((item) => { return item === file.url })
            console.log(currentIndex, imageList, file.url)
            this.$viewerApi({
              options: {
                navbar: true,
                fullscreen: false,
                inline: true,
                initialViewIndex: currentIndex
              },
              images: imageList
            })
          }
        }
      },
      // 自定义上传
      customRequest (data) {
        // 找到对应的上传文件对象
        const fileJson = this.fileList.find(item => {
          return data.file.uid === item.uid
        })
        // 自定义上传服务器
        if (this.customRequestPro) {
          // 自定义请求
          this.customRequestPro(data, fileJson, (isSuccess) => {
            // uploading(上传中)、done(上传成功)、error(上传失败)
            const status = isSuccess ? 'done' : 'error'
            this.customRequestResult(fileJson, status)
          })
        } else {
          // 开始上传
          uploadCustom(fileJson, this.uploadResult)
        }
      },

      // 准备上传
      beforeUpload (file, fileList) {
        if (this.listType === 'picture-card') {
            const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg'
          if (!isJpgOrPng) {
            this.$message.error('只能上传图片')
            return
          }
        }

        // 开始检测
        return new Promise((resolve, reject) => {
          // ----------------------------- 公用赋值 - 配置上传本轮唯一ID --------

          // 获取上传本轮唯一ID,检查 file 对象是否有带本轮唯一ID
          var uploadId = file.uploadId
          // 没有则是新的一轮选择,需要新获取本轮唯一ID
          if (!uploadId) {
            // 获取到本轮唯一ID
            uploadId = this.getUploadId()
            // 全部文件进行赋值
            fileList.forEach(item => {
              item.uploadId = uploadId
            })
          }

          // ----------------------------- 公用检测 - 文件数量限制 --------

          // 总文件数量
          if (this.fileNumber !== 0) {
            // 文件总数量
            const total = this.fileList.length + fileList.length
            // 如果文件总数量超过文件限制数量则停止上传
            if (total > this.fileNumber) {
              // 是否允许抛出错误
              if (!this.isExistErrorUploadId(uploadId)) {
                // 有错误回调
                if (this.fileNumberErrorPro) {
                  // 错误回调
                  this.fileNumberErrorPro(file, fileList, uploadId)
                } else {
                  // 有错误文案
                  if (this.fileNumberError) {
                    this.showError(this.fileNumberError)
                  }
                }
              }
              // 不允许上传
              reject(new Error())
              return
            }
          }

          // ----------------------------- 公用检测 - 文件检测 --------

          // 文件对象
          const fileJson = {
            id: file.uid,
            // 唯一标识符
            uid: file.uid,
            // 文件名
            name: file.name,
            // 文件状态:uploading(上传中)、done(上传成功)、error(上传失败)
            status: 'uploading',
            // 防止重复标识
            dupid: file.lastModified,
            // 本轮上传ID(上传服务器可剔除)
            upid: uploadId,
            // 文件信息
            file: file,
            url: '',
            // 其他自用字段可自行附带
            // 文件地址
            filePath: file.filePath
          }

          // 文件检测 - 同步
          if (this.fileCheckMode !== 0) {
            // 匹配检测模式
            if (this.fileCheckMode === 1) {
              // 本次选择的所有文件,检测失败的移除,成功的上传
              this.fileCheck(file, fileList, uploadId).then(() => {
                // 准备上传 预处理 结束
                this.beforeUploadProEnd(file, fileList, fileJson, resolve, reject)
              }).catch(() => {
                // 不允许上传
                reject(new Error())
              })
            } else if (this.fileCheckMode === 2) {
              // 本次选择的所有文件,有一个检测失败,全部移除
              // Promise 数组
              const ps = []
              // 存放 Promise
              fileList.forEach(item => {
                ps.push(this.fileCheck(item, fileList, uploadId))
              })
              // 全部请求
              Promise.all(ps).then(() => {
                // 准备上传 预处理 结束
                this.beforeUploadProEnd(file, fileList, fileJson, resolve, reject)
              }).catch(() => {
                // 不允许上传
                reject(new Error())
              })
            } else {
              // 准备上传 预处理 结束
              this.beforeUploadProEnd(file, fileList, fileJson, resolve, reject)
            }
          } else {
            // 准备上传 预处理 结束
            this.beforeUploadProEnd(file, fileList, fileJson, resolve, reject)
          }
        })
      },
      // 准备上传 - 预处理 结束
      beforeUploadProEnd (file, fileList, fileJson, resolve, reject) {
        // 准备上传 预处理
        this.beforeUploadProReady(file, fileList, fileJson).then(() => {
          // 加入文件列表
          this.fileList.push(fileJson)
          // 允许上传
          resolve()
        }).catch(() => {
          // 不允许上传
          reject(new Error())
        })
      },
      // 准备上传 - 预处理 开始
      beforeUploadProReady (file, fileList, fileJson) {
        // 预处理
        return new Promise((resolve, reject) => {
          // 外传回调
          if (this.beforeUploadPro) {
            // 获取回调结果
            const p = this.beforeUploadPro(file, fileList, fileJson)
            // 检测返回类型
            if (typeof (p) === 'boolean') {
              // 是否为 Boolean
              if (p) {
                // 允许上传
                resolve()
              } else {
                // 不允许上传
                reject(new Error())
              }
            } else if (!!p && (typeof (p) === 'object' || typeof obj === 'function') && typeof (p.then) === 'function') {
              // 是否为 Promise
              p.then(() => {
                // 允许上传
                resolve()
              }).catch(() => {
                // 不允许上传
                reject(new Error())
              })
            }
          } else {
            // 允许上传
            resolve()
          }
        })
      },
      // 点击移除文件时的回调
      remove (file) {
        // 预处理
        return new Promise((resolve, reject) => {
          // 外传回调
          if (this.removePro) {
            // 获取回调结果
            const p = this.removePro(file)
            // 检测返回类型
            if (typeof (p) === 'boolean') {
              // 是否为 Boolean
              if (p) {
                // 删除文件
                const index = this.fileList.indexOf(file)
                this.fileList.splice(index, 1)
                // 允许删除
                resolve()
              } else {
                // 不允许删除
                reject(new Error())
              }
            } else if (!!p && (typeof (p) === 'object' || typeof obj === 'function') && typeof (p.then) === 'function') {
              // 是否为 Promise
              p.then(() => {
                // 删除文件
                const index = this.fileList.indexOf(file)
                this.fileList.splice(index, 1)
                // 允许上传
                resolve()
              }).catch(() => {
                // 不允许删除
                reject(new Error())
              })
            }
          } else {
            // 删除文件
            const index = this.fileList.indexOf(file)
            this.fileList.splice(index, 1)
            // 允许删除
            resolve()
          }
        })
      },
      // 文件下载
      download (file) {
        downloadCustom(file, this.downloadPro)
      },
      // 文件检测 - 同步
      fileCheck (file, fileList, uploadId) {
        // 预处理
        return new Promise((resolve, reject) => {
          // ----------------------------- 公用检测 - 文件重复 --------

          // 判断重复文件
          if (this.fileRepeatMode !== 0) {
            // 获取重复列表
            const repeatFiles = []
            fileList.forEach(itemOne => {
              this.fileList.some(itemTwo => {
                // 检测到重复文件 名称相同 && 最后修改时间相同 && 上传ID不相同
                const isRepeat = itemOne.name === itemTwo.name && itemOne.lastModified === itemTwo.dupid && uploadId !== itemTwo.upid
                if (isRepeat) {
                  repeatFiles.push(itemOne)
                }
                return isRepeat
              })
            })
            // 根据重复类型检测
            if (this.fileRepeatMode === 1) {
              // 禁止重复文件(多选模式:本次选择的所有文件,重复文件移除,不重复文件上传)
              const isRepeat = this.fileList.some(item => {
                return file.name === item.name && file.lastModified === item.dupid
              })
              // 存在重复
              if (isRepeat) {
                // 是否允许抛出错误
                if (!this.isExistErrorUploadId(uploadId)) {
                  // 有错误回调
                  if (this.fileRepeatErrorPro) {
                    // 错误回调
                    this.fileRepeatErrorPro(file, fileList, uploadId, repeatFiles)
                  } else {
                    // 有错误文案
                    if (this.fileRepeatError) {
                      this.showError(this.fileRepeatError)
                    }
                  }
                }
                // 检测失败
                reject(new Error())
                return
              }
            } else if (this.fileRepeatMode === 2) {
              // 禁止重复文件(多选模式:本次选择的所有文件,有一个存在重复,全部移除)
              const isRepeat = Boolean(repeatFiles.length)
              // 存在重复
              if (isRepeat) {
                // 是否允许抛出错误
                if (!this.isExistErrorUploadId(uploadId)) {
                  // 有错误回调
                  if (this.fileRepeatErrorPro) {
                    // 错误回调
                    this.fileRepeatErrorPro(file, fileList, uploadId, repeatFiles)
                  } else {
                    // 有错误文案
                    if (this.fileRepeatError) {
                      this.showError(this.fileRepeatError)
                    }
                  }
                }
                // 检测失败
                reject(new Error())
                return
              }
            }
          }

          // ----------------------------- 公用检测 - 文件大小 --------

          // 开启了 - 文件大小检测
          if (this.kbCompareMode !== 0) {
            // 检测结果
            var isOK = true
            // 获取文件大小(单位:kb)
            const fileSize = file.size / 1024
            // 开始检测
            if (this.kbCompareMode === 1) {
              // 小于
              isOK = fileSize < this.kbCompareSize
            } else if (this.kbCompareMode === 2) {
              // 大于
              isOK = fileSize > this.kbCompareSize
            } else if (this.kbCompareMode === 3) {
              // 等于
              isOK = fileSize === this.kbCompareSize
            } else if (this.kbCompareMode === 11) {
              // 小于等于
              isOK = fileSize <= this.kbCompareSize
            } else if (this.kbCompareMode === 22) {
              // 大于等于
              isOK = fileSize >= this.kbCompareSize
            } else {
            }
            // 判断检测结果
            if (!isOK) {
              // 是否允许抛出错误
              if (!this.isExistErrorUploadId(uploadId)) {
                // 有错误回调
                if (this.kbCompareErrorPro) {
                  // 错误回调
                  this.kbCompareErrorPro(file, fileList, uploadId)
                } else {
                  // 有错误文案
                  if (this.kbCompareError) {
                    this.showError(this.kbCompareError)
                  }
                }
              }
              // 检测失败
              reject(new Error())
              return
            }
          }

          // ----------------------------- 图片检查 - 宽高限制 - 比例限制 --------

          // 图片检测
          if ((this.imgSizeMode !== 0 || this.imgScaleMode !== 0) &&
           this.isImage(file.name)) {
            // 获取图片宽高
            this.imageSize(file, (imgWidth, imgHeight) => {
              // 图片检测 - 宽高限制
              if (this.imgSizeMode !== 0) {
                // 检测结果
                var isOK = true
                // 开始检测
                if (this.imgSizeMode === 1) {
                  // 小于
                  isOK = (imgWidth < this.imgSizeWidth && imgHeight < this.imgSizeHeight)
                } else if (this.kbCompareMode === 2) {
                  // 大于
                  isOK = (imgWidth > this.imgSizeWidth && imgHeight > this.imgSizeHeight)
                } else if (this.imgSizeMode === 3) {
                  // 等于
                  isOK = (imgWidth === this.imgSizeWidth && imgHeight === this.imgSizeHeight)
                } else if (this.imgSizeMode === 11) {
                  // 小于等于
                  isOK = (imgWidth <= this.imgSizeWidth && imgHeight <= this.imgSizeHeight)
                } else if (this.imgSizeMode === 22) {
                  // 大于等于
                  isOK = (imgWidth >= this.imgSizeWidth && imgHeight >= this.imgSizeHeight)
                } else {
                }
                // 判断检测结果
                if (!isOK) {
                  // 是否允许抛出错误
                  if (!this.isExistErrorUploadId(uploadId)) {
                    // 有错误回调
                    if (this.imgSizeErrorPro) {
                      // 错误回调
                      this.imgSizeErrorPro(file, fileList, uploadId)
                    } else {
                      // 有错误文案
                      if (this.imgSizeError) {
                        this.showError(this.imgSizeError)
                      }
                    }
                  }
                  // 检测失败
                  reject(new Error())
                  return
                }
              }
              // 图片检测 - 比例限制
              if (this.imgScaleMode !== 0) {
                // 检测结果
                var isWidth = (imgWidth % this.imgScaleWidth) === 0
                var isHeight = (imgHeight % this.imgScaleHeight) === 0
                // 判断检测结果
                if (!isWidth && !isHeight) {
                  // 是否允许抛出错误
                  if (!this.isExistErrorUploadId(uploadId)) {
                    // 有错误回调
                    if (this.imgScaleErrorPro) {
                      // 错误回调
                      this.imgScaleErrorPro(file, fileList, uploadId)
                    } else {
                      // 有错误文案
                      if (this.imgScaleError) {
                        this.showError(this.imgScaleError)
                      }
                    }
                  }
                  // 检测失败
                  reject(new Error())
                  return
                }
              }
              // 检测成功
              resolve()
            })
            // 不要在向下走了
            return
          }

          // ----------------------------- 视频检查 - 宽高限制 - 比例限制 --------

          // 视频检测
          if ((this.videSizeMode !== 0 || this.videScaleMode !== 0) && this.isVideo(file.name)) {
            // 获取图片宽高
            this.videoSize(file, (videoWidth, videoHeight) => {
              // 图片检测 - 宽高限制
              if (this.videSizeMode !== 0) {
                // 检测结果
                var isOK = true
                // 开始检测
                if (this.videSizeMode === 1) {
                  // 小于
                  isOK = (videoWidth < this.videSizeWidth && videoHeight < this.videSizeHeight)
                } else if (this.videSizeMode === 2) {
                  // 大于
                  isOK = (videoWidth > this.videSizeWidth && videoHeight > this.videSizeHeight)
                } else if (this.videSizeMode === 3) {
                  // 等于
                  isOK = (videoWidth === this.videSizeWidth && videoHeight === this.videSizeHeight)
                } else if (this.videSizeMode === 11) {
                  // 小于等于
                  isOK = (videoWidth <= this.videSizeWidth && videoHeight <= this.videSizeHeight)
                } else if (this.videSizeMode === 22) {
                  // 大于等于
                  isOK = (videoWidth >= this.videSizeWidth && videoHeight >= this.videSizeHeight)
                } else {
                }
                // 判断检测结果
                if (!isOK) {
                  // 是否允许抛出错误
                  if (!this.isExistErrorUploadId(uploadId)) {
                    // 有错误回调
                    if (this.videSizeErrorPro) {
                      // 错误回调
                      this.videSizeErrorPro(file, fileList, uploadId)
                    } else {
                      // 有错误文案
                      if (this.videSizeError) {
                        this.showError(this.videSizeError)
                      }
                    }
                  }
                  // 检测失败
                  reject(new Error())
                  return
                }
              }
              // 图片检测 - 比例限制
              if (this.videScaleMode !== 0) {
                // 检测结果
                var isWidth = (videoWidth % this.videScaleWidth) === 0
                var isHeight = (videoHeight % this.videScaleHeight) === 0
                // 判断检测结果
                if (!isWidth && !isHeight) {
                  // 是否允许抛出错误
                  if (!this.isExistErrorUploadId(uploadId)) {
                    // 有错误回调
                    if (this.videScaleErrorPro) {
                      // 错误回调
                      this.videScaleErrorPro(file, fileList, uploadId)
                    } else {
                      // 有错误文案
                      if (this.videScaleError) {
                        this.showError(this.videScaleError)
                      }
                    }
                  }
                  // 检测失败
                  reject(new Error())
                  return
                }
              }
              // 检测成功
              resolve()
            })
            // 不要在向下走了
            return
          }

          // ----------------------------- 检测成功 --------

          // 检测成功
          resolve()
        })
      },
      // 显示错误,统一管理,方便替换
      showError (message) {
        // 显示错误
        this.$message.error(message)
      },
      // 自定义上传结果
      customRequestResult (fileJson, status) {
        // 设置上传状态
        fileJson.status = status
      },
      // 获取本次上传唯一ID
      getUploadId () {
        // 返回
        return this.getUUID()
      },
      // 是否存在本轮错误 uploadId
      isExistErrorUploadId (uploadId) {
        // 当为错误唯一模式的时候才需要检测
        if (this.errorMode === 1) {
          const index = this.errorUploadIds.indexOf(uploadId)
          const isExist = index !== -1
          if (!isExist) {
            this.errorUploadIds.push(uploadId)
          }
          return isExist
        }
        // 不包含
        return false
      },
      // 获取图片尺寸(异步获取)
      imageSize (file, result) {
        // 文件有值
        if (file) {
          // 创建 FileReader
          var reader = new FileReader()
          // 加载文件
          reader.onload = (e) => {
            // 获取 base64 图片数据
            var imgData = e.target.result
            // 通过Image对象加载 base64 图片数据
            var image = new Image()
            // 图片加载完成
            image.onload = () => {
              // 返回宽高
              result(image.width, image.height)
            }
            // 添加图片进行读取
            image.src = imgData
          }
          // 开始读取文件
          reader.readAsDataURL(file)
        } else {
          // 未获取到文件
          result(0, 0)
        }
      },
      // 获取视频尺寸(异步获取)
      videoSize (file, result) {
        // 文件有值
        if (file) {
          // 获取文件URL
          const url = URL.createObjectURL(file)
          // 创建视频标签
          const video = document.createElement('video')
          // 加载视频资源
          video.onloadedmetadata = evt => {
            // 移除
            URL.revokeObjectURL(url)
            // 返回宽高
            result(video.videoWidth, video.videoHeight)
          }
          // 设置视频源
          video.src = url
          // 加载
          video.load()
        } else {
          // 未获取到文件
          result(0, 0)
        }
      },
      // 是否为图片
      isImage (filePath) {
        // 图片后缀
        const types = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff']
        // 文件后缀
        const type = this.fileExtension(filePath)
        // 是否包含
        return types.indexOf(type) !== -1
      },
      // 是否为视频
      isVideo (filePath) {
        // 图片后缀
        const types = ['avi', 'wmv', 'mpg', 'mpeg', 'mov', 'rm', 'ram', 'swf', 'flv', 'mp4', 'mp3', 'wma', 'avi', 'rm', 'rmvb', 'flv', 'mpg', 'mkv']
        // 文件后缀
        const type = this.fileExtension(filePath)
        // 是否包含
        return types.indexOf(type) !== -1
      },
      // 获取文件后缀类型
      fileExtension (filePath) {
        // 获取最后一个.的位置
        var index = filePath.lastIndexOf('.')
        // 获取后缀
        var type = filePath.substr(index + 1)
        // 返回类型
        return type.toLowerCase()
      }
    }
  }
</script>

<style>

</style>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Ant Design Vue提供的Upload组件来实现文件上传。具体步骤如下: 1. 安装Ant Design Vue和Axios: ```bash npm install ant-design-vue axios --save ``` 2. 在main.js中引入Ant Design Vue和样式: ```javascript import Vue from 'vue'; import Antd from 'ant-design-vue'; import 'ant-design-vue/dist/antd.css'; Vue.use(Antd); ``` 3. 在组件中使用Upload组件: ```vue <template> <a-upload :action="uploadUrl" :headers="headers" :before-upload="beforeUpload" :on-success="onSuccess" > <a-button icon="upload">上传文件</a-button> </a-upload> </template> <script> import axios from 'axios'; export default { data() { return { uploadUrl: 'http://localhost:3000/upload', // 上传接口 headers: { 'Authorization': 'Bearer ' + localStorage.getItem('token') }, // 请求头部 }; }, methods: { beforeUpload(file) { // 限制上传文件的类型和大小 const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; if (!isJpgOrPng) { this.$message.error('只能上传 JPG/PNG 文件!'); return false; } const isLt2M = file.size / 1024 / 1024 < 2; if (!isLt2M) { this.$message.error('文件大小不能超过 2MB!'); return false; } return true; }, onSuccess(response) { this.$message.success('上传成功!'); }, }, }; </script> ``` 在上面的代码中,我们定义了一个Upload组件,设置了上传接口、请求头部、限制上传文件类型和大小的beforeUpload方法和上传成功的onSuccess方法。 需要注意的是,这里使用了Axios来发送请求,所以需要在组件中引入Axios。同时,需要在请求头部中带上Authorization字段,用于校验用户是否登录。你需要根据实际情况修改这些值。 另外,如果需要在上传成功后展示上传的文件,可以在onSuccess方法中调用接口获取文件列表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值