最近在使用Aidex-Sharp前端开源框架,发现文件上传没有,想着自己通过官网写一个,没想到发现了些问题,并附上解决得方法。

问题:

a-upload组件没有专门针对上传成功得回调,只有一个......

然后紧接着无数个问题开始了。

1、无论上传成功或者失败,file.status永远为uploading.

2、通过beforeUpload,做的一系列校验,该方法返回false,按照官网应该停止上传了,但是还是根本拦不住,还上上传了。

3、判断不了是否成功上传,判断不了成功后得url等。

进入正题

解决办法不唯一

但是该方法可以。是通过自定义得上传行为实现。

customRequest通过覆盖默认的上传行为,可以自定义自己的上传实现

具体实现

一、目录结构及部分代码截图

二、页面调用ImageUpload组件

在需要使用得页面按需要引入然后调用即可,数量、问价文件类型、文件大小等限制

import ImageUpload from '@/components/ImageUpload'
<ImageUpload v-model="form.imgId" :limit='3' :fileType="fileType"/>

三、给出默认值

四、完美效果

五、删除图片

六、完整代码

<template>
  <div class="clearfix">
    <a-upload
      :action="uploadImgUrl"
      :headers="headers"
      :list-type="type === 'image' ? 'picture-card' : 'picture'"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :customRequest="customRequest"
      @preview="handlePreview"
      @change="handleChange"
    >
      <div v-if="fileList.length < limit">
        <a-icon type="plus" />
        <div class="ant-upload-text">
          上传
        </div>
      </div>
    </a-upload>
    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
      <img alt="example" style="width: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>
<script>
  import axios from 'axios'
  import storage from 'store'
  import { ACCESS_TOKEN } from '@/store/mutation-types'
  function getBase64(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => resolve(reader.result)
      reader.onerror = error => reject(error)
    })
  }
  export default {
    name: 'FileUpload',
    props: {
      // 默认值
      value: [String, Object, Array],
      // 文件类型
      type: {
        type: String,
        default: 'image'
      },
      // 大小限制(MB)
      fileSize: {
        type: Number,
        default: 5
      },
      // 个数限制
      limit: {
        type: Number,
        default: 5
      },
      // 文件类型, 例如['png', 'jpg', 'jpeg']
      fileType: {
        type: Array,
        default: () => ['png', 'jpg', 'jpeg']
      }
    },
    components: {
    },
    data() {
      return {
        uploadImgUrl: process.env.VUE_APP_BASE_API + '/common/upload',
        headers: {
          Authorization: 'Bearer ' + storage.get(ACCESS_TOKEN)
        },
        previewVisible: false,
        previewImage: '',
        fileList: []
      }
    },

    watch: {
      value: {
        handler(val) {
          if (val) {
            let temp = 1
            // 首先将值转为数组
            const list = Array.isArray(val) ? val : this.value.split(',')
            // 然后将数组转为对象数组
            this.fileList = list.map(item => {
              if (typeof item === 'string') {
                item = { name: item, url: item, status: 'done' }
              }
              item.uid = item.uid || new Date().getTime() + temp++
              return item
            })
          } else {
            this.fileList = []
            return []
          }
        },
        deep: true,
        immediate: true
      }
    },
    methods: {
      beforeUpload(file) {
        // 校检文件类型
        if (this.fileType) {
          let fileExtension = ''
          if (file.name.lastIndexOf('.') > -1) {
            fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
          }
          const isTypeOk = this.fileType.some((type) => {
            if (file.type.indexOf(type) > -1) return true
            if (fileExtension && fileExtension.indexOf(type) > -1) return true
            return false
          })
          if (!isTypeOk) {
            this.$message.error(`文件格式不正确, 请上传${this.fileType.join('/')}格式文件!`)
            return false
          }
        }
        // 校检文件大小
        if (this.fileSize) {
          const isLt = file.size / 1024 / 1024 < this.fileSize
          if (!isLt) {
            this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
            return false
          }
        }
        return true
      },
      handleCancel() {
        this.previewVisible = false
      },
      async handlePreview(file) {
        if (!file.url && !file.preview) {
          file.preview = await getBase64(file.originFileObj)
        }
        this.previewImage = file.url || file.preview
        this.previewVisible = true
      },
      // 自定义上传,可以自定义上传接口,不用通过action属性,还是非常灵活的
      customRequest(file) {
        // file 是上传的文件 其内容会在放在下面截图中
        // 后端需要接受的参数是 formData数据,
        const form = new FormData()
        form.append('file', file.file)
        // uploadFile 我自己的接口
        this.uploadFile(form).then(res => {
          if (res.status === 200) {
            this.$message.success('上传成功')
            var fileItem = { name: res.data.fileName, uid: new Date().getTime() + 121, url: res.data.url, status: 'done' }
            this.fileList.push(fileItem)
            var toString = this.listToString(this.fileList)
            this.$emit('input', toString)
          } else {
            this.$message.error('上传失败')
          }
        })
      },
      // 设置好头部
      uploadFile (parameter) {
        return axios({
          url: this.uploadImgUrl,
          method: 'post',
          headers: { 'Content-Type': 'multipart/form-data', 'Authorization': this.headers.Authorization },
          data: parameter
        })
      },
      // 对象转成指定','字符串分隔
      listToString(list, separator) {
        console.log(list)
        let strs = ''
        separator = separator || ','
        for (var i in list) {
          var url = list[i].url
          strs += url + separator
        }
        return strs !== '' ? strs.substr(0, strs.length - 1) : ''
      },
      async handleChange (info) {
        if (info.file.status === 'removed') {
          this.$message.success('删除成功')
          this.fileList = info.fileList
          var toString = this.listToString(this.fileList)
          this.$emit('input', toString)
        }
      }
    }
  }
</script>

<style>
  /* you can make up upload button and sample style by using stylesheets */
  .ant-upload-select-picture-card i {
    font-size: 32px;
    color: #999;
  }

  .ant-upload-select-picture-card .ant-upload-text {
    margin-top: 8px;
    color: #666;
  }
</style>

如果有用,欢迎关注~~~

GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐