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上传文件限制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程
这篇文章主要介绍了基于Vue3实现一个前端埋点上报插件并打包发布到npm,本项目采用pnpm进行Monorepo环境搭建,因为未来这个项目可能会加入更多的工具包,需要的朋友可以参考下2022-10-10
最新评论