Vue 使用 ElementUi el-upload 手动上传文件限制上传文件类型大小同名等进行限制

 更新时间:2024年02月06日 11:32:22   作者:小熊猫Yzt_199626  
个人在做文件上传功能的时候,踩过不少的坑,特在此记录下,本文介绍Vue使用 ElementUi el-upload 手动上传文件限制上传文件类型大小同名等进行限制问题,感兴趣的朋友一起看看吧

个人在做文件上传功能的时候,踩过不少的坑,特在此记录下,方便后续的查阅,也帮助有需要的个人在开发中,需要做文件的上传,自己踩过不少的坑,于是决定在此记录以下,方便自己后续查看,也方便有需要的朋友查阅。

实现的功能有:文件上传类型限制、文件大小限制、文件总大小限制、文件同名限制、文件下载、文件删除 和 文件预览图。

效果图如下:

1. 文件类型限制

2. 文件大小限制

3. 文件同名限制

4. 文件总大小限制

5. 文件下载和删除

6. 文件预览图就是上述的框体图片,这个是自己引入的图片,自己会放在附件处。有需要的可到  阿里巴巴icon图库官网 进行下载自己喜欢的图片。

7. 点击保存上传文件等信息

下面来说下大致的实现过程,让大家更明确一些。

前提:要手动上传文件,需要将 :auto-upload="false" 加上,指的是不要自动上传。自己书写下 :http-request="handleUplodFile" 方法,覆盖 action 即可。

自己定义了两个变量:

 fileList:[] : 是用于展示选择的文件列表的,如上面的一个个的框体。

realUploadFile:[] :这个是真实的要上传给后端的文件,该数组的类型是 二进制的Object 类型

下面直接说下关键的代码

1. 文件上传的时候,触发 on-change 事件,在这可做一些判断。文件类型限制、文件大小限制、文件同名限制和文件总大小限制等等。

    // 文件勾选触发
    changUpload(file) {
      const { uid, name, size } = file
      //   文件类型限制
      const fileTypeFlag = /^.png|.jpg|.jpeg|.gif|.txt|.doc|.docx|.xls|.xlsx|.pdf|.zip|.7z|.rar$/.test(
        name.substring(name.lastIndexOf('.')).toLowerCase()
      )
      if (!fileTypeFlag) {
        this.$message.warning(
          '文件类型只能是.png|.jpg|.jpeg|.gif|.doc|.docx|.xls|.xlsx|.pdf|.zip|.7z|.rar|.txt'
        )
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   文件大小进行校验
      if (size > 1024 * 1024 * 100) {
        this.$message.warning('文件大小不能超过100Mb')
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   文件总大小限制
      const totalSize = this.modelForm.fileList.reduce(
        (total, item) => total + item.size,
        0
      )
      if (totalSize + size > 1024 * 1024 * 100) {
        this.$message.warning('总文件大小不能超过100Mb')
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   文件重名限制
      const findCommonNameIndex = this.modelForm.fileList.findIndex(
        item => item.name == name
      )
      if (findCommonNameIndex !== -1) {
        this.$message.warning('不能上传同名的文件')
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   将上传的文件信息存入列表
      this.modelForm.fileList.push(file)
      this.realUploadFile = []
    },

2. 文件的删除和下载。删除其实就是将已经勾选的文件移除列表,下载就是创建 a 标签,通过href 的方式下载。注意:在这不推荐使用 window.open, 因为下载下来的 的文件名是 哈希名,不符合要求。

    // 移除不需要的文件
    handleRemove(file) {
      const { uid } = file
      const selectFileList = this.modelForm.fileList.filter(item => {
        return item.uid != uid
      })
      this.modelForm.fileList = selectFileList
    },
    // 下载文件
    handleDownload(file) {
      const { url, name } = file
      let downloadLink = document.createElement('a')
      downloadLink.href = url
      downloadLink.download = name
      document.body.appendChild(downloadLink)
      downloadLink.click()
      document.body.removeChild(downloadLink)
    },

3. 实际要上传的文件。:http-request="handleUplodFile" 该事件就是自己实际要上传的文件,触发该方法是需要通过  this.$refs['uploadBlock'].submit() 来进行,然后就会将需要上传的文件压入数组中。

// 要上传文件压入数组
handleUplodFile(file) {
  this.realUploadFile.push(file.file)
},
// 点击保存
handleHttpUpload() {
 this.$refs['uploadBlock'].submit()
......
}

4. 点击保存,上传文件等相关信息。这里使用到的是 FormData() 对象,通过 append 追加的方式,将文件和其他信息放入该 FromData() 对象中。

    // 点击保存
    handleHttpUpload() {
      this.$refs['uploadBlock'].submit()
      let formData = new FormData() //formdata格式
      formData.append('info', JSON.stringify(this.modelForm))
      this.realUploadFile.forEach(file => {
        formData.append('file', file, file.name)
      })
      fileUpload(formData).then(resonse => {
        console.log(resonse)
      })
    // 一定要先清空真实文件数组,免得点击几次,真实文件一直压入该数组
      this.$nextTick(() => {
        this.realUploadFile = []
      })
    },

5. 自己写的后端 api 接口,以及如何使用她

/***** api 接口******/
export function fileUpload(data) {
  return request({
    url: '/file/upload',
    method: 'post',
    data
  })
}
/*****调用api*****/
import { fileUpload } from '@/api/user'
......
fileUpload(formData).then(resonse => {
        console.log(resonse)
})
/******** 提示:若是需要查看到文件上传的进度,可以使用如下配置 ******************/
/***** api 接口******/
export function fileUpload(data, config) {
  return request({
    url: '/file/upload',
    method: 'post',
    data,
    ...config
  })
}
/*****调用api*****/
import { fileUpload } from '@/api/user'
......
const config = {
    timeout: 120000,
    onUploadProgress: function(process) {
        const num = process.loaded / process.total * 100 | 0
        // 将数据赋值给进度条
        this.processNum = num
    }
}
fileUpload(formData, config).then(resonse => {
        console.log(resonse)
})

6. 完整的demo 代码如下

<template>
  <div>
    <el-form ref="searchform" :model="modelForm" label-width="150px">
      <el-form-item label="select多选demo:" prop="selectValue">
        <el-select
          v-model="modelForm.selectValue"
          @change="changeSelect"
          multiple
          clearable
          placeholder="请选择"
        >
          <el-option key="selectAll" label="全部" value="selectAll"></el-option>
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="附件" prop="fileList">
        <el-upload
          ref="uploadBlock"
          action="#"
          list-type="picture-card"
          :file-list="modelForm.fileList"
          accept=".png,.jpg,.jpeg,.gif,.txt,.doc,.docx,.xls,.xlsx,.pdf,.zip,.7z,.rar"
          :auto-upload="false"
          :on-change="changUpload"
          :http-request="handleUplodFile"
        >
          <i slot="default" class="el-icon-plus"></i>
          <div slot="file" slot-scope="{ file }">
            <img
              class="el-upload-list__item-thumbnail"
              :src="getPreviwImg(file.name)"
              alt=""
            />
            <el-tooltip :content="file.name" placement="bottom" effect="light">
              <span class="el-upload-list__item-actions">
                <span
                  class="el-upload-list__item-delete"
                  @click="handleDownload(file)"
                >
                  <i class="el-icon-download"></i>
                </span>
                <span
                  class="el-upload-list__item-delete"
                  @click="handleRemove(file)"
                >
                  <i class="el-icon-delete"></i>
                </span>
              </span>
            </el-tooltip>
          </div>
        </el-upload>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleHttpUpload">保存</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import { fileUpload } from '@/api/user'
export default {
  data() {
    return {
      options: [
        {
          value: '选项1',
          label: '黄金糕'
        },
        {
          value: '选项2',
          label: '双皮奶'
        },
        {
          value: '选项3',
          label: '蚵仔煎'
        },
        {
          value: '选项4',
          label: '龙须面'
        },
        {
          value: '选项5',
          label: '北京烤鸭'
        }
      ],
      modelForm: {
        selectValue: [],
        fileList: []
      },
      realUploadFile: [], // 真实上传的文件
      selectAll: false // 用于标识是否全选--默认不全选
    }
  },
  created() {},
  methods: {
    changeSelect(value) {
      //  selectAll 为true 的时候,就走全选分支,全选后出现的情况就是取消权限
      if (this.selectAll) {
        this.selectAll = false
        if (value.indexOf('selectAll') > -1) {
          this.modelForm.selectValue = value.filter(p => p != 'selectAll')
        } else {
          this.modelForm.selectValue = []
        }
      } else {
        //   是否点击了‘全选'选项
        if (value.indexOf('selectAll') > -1) {
          // 有‘全选'选项,则将‘全部'和其他值放置一块
          const optionsValue = []
          this.options.forEach(item => {
            optionsValue.push(item.value)
          })
          this.modelForm.selectValue = ['selectAll', ...optionsValue]
          this.selectAll = true
        } else {
          // 若是勾选选择的长度和提供的选项长度是一样的,则是 ‘全选'
          if (value.length === this.options.length) {
            const optionsValue = []
            this.options.forEach(item => {
              optionsValue.push(item.value)
            })
            this.modelForm.selectValue = ['selectAll', ...optionsValue]
            this.selectAll = true
          } else {
            //   都是单选
            this.modelForm.selectValue = value
          }
        }
      }
      // 真实的勾选值
      const realSelect = this.modelForm.selectValue.filter(
        item => item != 'selectAll'
      )
      console.log('realSelect', realSelect)
    },
    // 移除不需要的文件
    handleRemove(file) {
      const { uid } = file
      const selectFileList = this.modelForm.fileList.filter(item => {
        return item.uid != uid
      })
      this.modelForm.fileList = selectFileList
    },
    // 下载文件
    handleDownload(file) {
      const { url, name } = file
      let downloadLink = document.createElement('a')
      downloadLink.href = url
      downloadLink.download = name
      document.body.appendChild(downloadLink)
      downloadLink.click()
      document.body.removeChild(downloadLink)
    },
    // 文件勾选触发
    changUpload(file) {
      const { uid, name, size } = file
      //   文件类型限制
      const fileTypeFlag = /^.png|.jpg|.jpeg|.gif|.txt|.doc|.docx|.xls|.xlsx|.pdf|.zip|.7z|.rar$/.test(
        name.substring(name.lastIndexOf('.')).toLowerCase()
      )
      if (!fileTypeFlag) {
        this.$message.warning(
          '文件类型只能是.png|.jpg|.jpeg|.gif|.doc|.docx|.xls|.xlsx|.pdf|.zip|.7z|.rar|.txt'
        )
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   文件大小进行校验
      if (size > 1024 * 1024 * 100) {
        this.$message.warning('文件大小不能超过100Mb')
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   文件总大小限制
      const totalSize = this.modelForm.fileList.reduce(
        (total, item) => total + item.size,
        0
      )
      if (totalSize + size > 1024 * 1024 * 100) {
        this.$message.warning('总文件大小不能超过100Mb')
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   文件重名限制
      const findCommonNameIndex = this.modelForm.fileList.findIndex(
        item => item.name == name
      )
      if (findCommonNameIndex !== -1) {
        this.$message.warning('不能上传同名的文件')
        const selectFileList = this.modelForm.fileList.filter(item => {
          return item.uid != uid
        })
        this.modelForm.fileList = selectFileList
        return
      }
      //   将上传的文件信息存入列表
      this.modelForm.fileList.push(file)
      this.realUploadFile = []
    },
    // 要上传文件压入数组
    handleUplodFile(file) {
      this.realUploadFile.push(file.file)
    },
    // 点击保存
    handleHttpUpload() {
      this.$refs['uploadBlock'].submit()
      let formData = new FormData() //formdata格式
      formData.append('info', JSON.stringify(this.modelForm))
      this.realUploadFile.forEach(file => {
        formData.append('file', file, file.name)
      })
      fileUpload(formData).then(resonse => {
        console.log(resonse)
      })
      this.$nextTick(() => {
        this.realUploadFile = []
      })
    },
    getImgUrl(image) {
      return require(`@/assets/images/file/${image}`)
    },
    getPreviwImg(filename) {
      filename = filename
        .substring(filename.lastIndexOf('.'))
        .toLowerCase()
        .split('.')[1]
      const imageObject = {
        png: 'icon-png.png',
        jpg: 'icon-jpg.png',
        jpeg: 'icon-jpeg.png',
        gif: 'icon-gif.png',
        doc: 'icon-doc.png',
        docx: 'icon-doc.png',
        xls: 'icon-xls.png',
        xlsx: 'icon-xls.png',
        pdf: 'icon-pdf.png',
        zip: 'icon-zip.png',
        '7z': 'icon-zip.png',
        rar: 'icon-zip.png',
        txt: 'icon-txt.png'
      }
      return this.getImgUrl(imageObject[filename])
    }
  }
}
</script>
<style lang="scss" scoped></style>

上述用到图片的附件:

上一篇:第十五篇 VUE中使用 ElementUi 的 el-select 实现全选功能

到此这篇关于Vue 使用 ElementUi el-upload 手动上传文件限制上传文件类型大小同名等进行限制的文章就介绍到这了,更多相关Vue ElementUi el-upload上传文件限制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue中常用的鼠标移入移出事件详解

    Vue中常用的鼠标移入移出事件详解

    这篇文章主要给大家介绍了关于Vue中常用的鼠标移入移出事件的相关资料,鼠标移入移出事件在 Vue 中可以通过@mouseenter和@mouseleave来绑定,需要的朋友可以参考下
    2023-07-07
  • vue2.0使用Sortable.js实现的拖拽功能示例

    vue2.0使用Sortable.js实现的拖拽功能示例

    本篇文章主要介绍了vue2.0使用Sortable.js实现的拖拽功能示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-02-02
  • Vue中接收二进制文件流实现pdf预览的方法

    Vue中接收二进制文件流实现pdf预览的方法

    本文主要介绍了Vue中接收二进制文件流实现pdf预览的方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • vue封装动态表格方式详解

    vue封装动态表格方式详解

    这篇文章主要为大家介绍了vue封装动态表格方式示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • vue 之 css module的使用方法

    vue 之 css module的使用方法

    这篇文章主要介绍了vue 之 css module的使用方法,css module目的为所有类名重新生成类名,有效避开了css权重和类名重复的问题,非常具有实用价值,需要的朋友可以参考下
    2018-12-12
  • 基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

    基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

    这篇文章主要介绍了基于Vue3实现一个前端埋点上报插件并打包发布到npm,本项目采用pnpm进行Monorepo环境搭建,因为未来这个项目可能会加入更多的工具包,需要的朋友可以参考下
    2022-10-10
  • Vue侦测相关api的实现方法

    Vue侦测相关api的实现方法

    这篇文章主要介绍了Vue侦测相关api,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • 基于vue--key值的特殊用处详解

    基于vue--key值的特殊用处详解

    这篇文章主要介绍了基于vue--key值的特殊用处详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • 10分钟快速上手VueRouter4.x教程

    10分钟快速上手VueRouter4.x教程

    Vue Router目前最新版本是4.X,本文主要主要介绍了10分钟快速上手VueRouter4.x教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • vue 折叠展示多行文本组件的实现代码

    vue 折叠展示多行文本组件的实现代码

    这篇文章主要介绍了vue 折叠展示多行文本组件,自动根据传入的expand判断是否需要折叠,非常完美,文章通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2021-10-10

最新评论