Vue?使用?ElementUi?el-upload?手動(dòng)上傳文件限制上傳文件類型大小同名等進(jìn)行限制
個(gè)人在做文件上傳功能的時(shí)候,踩過(guò)不少的坑,特在此記錄下,方便后續(xù)的查閱,也幫助有需要的個(gè)人在開(kāi)發(fā)中,需要做文件的上傳,自己踩過(guò)不少的坑,于是決定在此記錄以下,方便自己后續(xù)查看,也方便有需要的朋友查閱。
實(shí)現(xiàn)的功能有:文件上傳類型限制、文件大小限制、文件總大小限制、文件同名限制、文件下載、文件刪除 和 文件預(yù)覽圖。
效果圖如下:
1. 文件類型限制

2. 文件大小限制

3. 文件同名限制

4. 文件總大小限制

5. 文件下載和刪除

6. 文件預(yù)覽圖就是上述的框體圖片,這個(gè)是自己引入的圖片,自己會(huì)放在附件處。有需要的可到 阿里巴巴icon圖庫(kù)官網(wǎng) 進(jìn)行下載自己喜歡的圖片。
7. 點(diǎn)擊保存上傳文件等信息

下面來(lái)說(shuō)下大致的實(shí)現(xiàn)過(guò)程,讓大家更明確一些。
前提:要手動(dòng)上傳文件,需要將 :auto-upload="false" 加上,指的是不要自動(dòng)上傳。自己書寫下 :http-request="handleUplodFile" 方法,覆蓋 action 即可。
自己定義了兩個(gè)變量:
fileList:[] : 是用于展示選擇的文件列表的,如上面的一個(gè)個(gè)的框體。
realUploadFile:[] :這個(gè)是真實(shí)的要上傳給后端的文件,該數(shù)組的類型是 二進(jìn)制的Object 類型
下面直接說(shuō)下關(guān)鍵的代碼
1. 文件上傳的時(shí)候,觸發(fā) on-change 事件,在這可做一些判斷。文件類型限制、文件大小限制、文件同名限制和文件總大小限制等等。
// 文件勾選觸發(fā)
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
}
// 文件大小進(jìn)行校驗(yàn)
if (size > 1024 * 1024 * 100) {
this.$message.warning('文件大小不能超過(guò)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('總文件大小不能超過(guò)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. 文件的刪除和下載。刪除其實(shí)就是將已經(jīng)勾選的文件移除列表,下載就是創(chuàng)建 a 標(biāo)簽,通過(guò)href 的方式下載。注意:在這不推薦使用 window.open, 因?yàn)橄螺d下來(lái)的 的文件名是 哈希名,不符合要求。
// 移除不需要的文件
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. 實(shí)際要上傳的文件。:http-request="handleUplodFile" 該事件就是自己實(shí)際要上傳的文件,觸發(fā)該方法是需要通過(guò) this.$refs['uploadBlock'].submit() 來(lái)進(jìn)行,然后就會(huì)將需要上傳的文件壓入數(shù)組中。
// 要上傳文件壓入數(shù)組
handleUplodFile(file) {
this.realUploadFile.push(file.file)
},
// 點(diǎn)擊保存
handleHttpUpload() {
this.$refs['uploadBlock'].submit()
......
}4. 點(diǎn)擊保存,上傳文件等相關(guān)信息。這里使用到的是 FormData() 對(duì)象,通過(guò) append 追加的方式,將文件和其他信息放入該 FromData() 對(duì)象中。
// 點(diǎn)擊保存
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)
})
// 一定要先清空真實(shí)文件數(shù)組,免得點(diǎn)擊幾次,真實(shí)文件一直壓入該數(shù)組
this.$nextTick(() => {
this.realUploadFile = []
})
},5. 自己寫的后端 api 接口,以及如何使用她
/***** api 接口******/
export function fileUpload(data) {
return request({
url: '/file/upload',
method: 'post',
data
})
}
/*****調(diào)用api*****/
import { fileUpload } from '@/api/user'
......
fileUpload(formData).then(resonse => {
console.log(resonse)
})
/******** 提示:若是需要查看到文件上傳的進(jìn)度,可以使用如下配置 ******************/
/***** api 接口******/
export function fileUpload(data, config) {
return request({
url: '/file/upload',
method: 'post',
data,
...config
})
}
/*****調(diào)用api*****/
import { fileUpload } from '@/api/user'
......
const config = {
timeout: 120000,
onUploadProgress: function(process) {
const num = process.loaded / process.total * 100 | 0
// 將數(shù)據(jù)賦值給進(jìn)度條
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="請(qǐng)選擇"
>
<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: '選項(xiàng)1',
label: '黃金糕'
},
{
value: '選項(xiàng)2',
label: '雙皮奶'
},
{
value: '選項(xiàng)3',
label: '蚵仔煎'
},
{
value: '選項(xiàng)4',
label: '龍須面'
},
{
value: '選項(xiàng)5',
label: '北京烤鴨'
}
],
modelForm: {
selectValue: [],
fileList: []
},
realUploadFile: [], // 真實(shí)上傳的文件
selectAll: false // 用于標(biāo)識(shí)是否全選--默認(rèn)不全選
}
},
created() {},
methods: {
changeSelect(value) {
// selectAll 為true 的時(shí)候,就走全選分支,全選后出現(xiàn)的情況就是取消權(quán)限
if (this.selectAll) {
this.selectAll = false
if (value.indexOf('selectAll') > -1) {
this.modelForm.selectValue = value.filter(p => p != 'selectAll')
} else {
this.modelForm.selectValue = []
}
} else {
// 是否點(diǎn)擊了‘全選'選項(xiàng)
if (value.indexOf('selectAll') > -1) {
// 有‘全選'選項(xiàng),則將‘全部'和其他值放置一塊
const optionsValue = []
this.options.forEach(item => {
optionsValue.push(item.value)
})
this.modelForm.selectValue = ['selectAll', ...optionsValue]
this.selectAll = true
} else {
// 若是勾選選擇的長(zhǎng)度和提供的選項(xiàng)長(zhǎng)度是一樣的,則是 ‘全選'
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
}
}
}
// 真實(shí)的勾選值
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)
},
// 文件勾選觸發(fā)
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
}
// 文件大小進(jìn)行校驗(yàn)
if (size > 1024 * 1024 * 100) {
this.$message.warning('文件大小不能超過(guò)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('總文件大小不能超過(guò)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 = []
},
// 要上傳文件壓入數(shù)組
handleUplodFile(file) {
this.realUploadFile.push(file.file)
},
// 點(diǎn)擊保存
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 實(shí)現(xiàn)全選功能
到此這篇關(guān)于Vue 使用 ElementUi el-upload 手動(dòng)上傳文件限制上傳文件類型大小同名等進(jìn)行限制的文章就介紹到這了,更多相關(guān)Vue ElementUi el-upload上傳文件限制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue?cesium加載點(diǎn)與定位到指定位置的實(shí)現(xiàn)方法
Cesium是一個(gè)用于創(chuàng)建高性能、跨平臺(tái)的3D地球和地圖的開(kāi)源JavaScript庫(kù),它提供了許多功能,包括地理空間數(shù)據(jù)可視化、地理定位和地圖導(dǎo)航等,這篇文章主要介紹了vue?cesium加載點(diǎn)與定位到指定位置,需要的朋友可以參考下2024-03-03
Vue-router結(jié)合transition實(shí)現(xiàn)app前進(jìn)后退動(dòng)畫切換效果的實(shí)例
下面小編就為大家?guī)?lái)一篇Vue-router結(jié)合transition實(shí)現(xiàn)app前進(jìn)后退動(dòng)畫切換效果的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
vuepress項(xiàng)目側(cè)邊欄菜單配置使用方式
這篇文章主要介紹了vuepress項(xiàng)目側(cè)邊欄菜單配置使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
vue項(xiàng)目打包清除console.log的四種方法總結(jié)
大家在項(xiàng)目開(kāi)發(fā)的時(shí)候,需要看看一些后端接口返回的結(jié)果,會(huì)多次使用console.log項(xiàng)目開(kāi)發(fā)完成打包的時(shí)候,發(fā)現(xiàn)控制臺(tái)一堆的console.log,非常頭疼,下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目打包清除console.log的四種方法,需要的朋友可以參考下2023-04-04
vue Nprogress進(jìn)度條功能實(shí)現(xiàn)常見(jiàn)問(wèn)題
這篇文章主要介紹了vue Nprogress進(jìn)度條功能實(shí)現(xiàn),NProgress是頁(yè)面跳轉(zhuǎn)是出現(xiàn)在瀏覽器頂部的進(jìn)度條,本文通過(guò)實(shí)例代碼給大家講解,需要的朋友可以參考下2021-07-07
詳解如何創(chuàng)建并發(fā)布一個(gè) vue 組件
這篇文章主要介紹了詳解如何創(chuàng)建并發(fā)布一個(gè)vue組件,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
詳解使用vue-cli腳手架初始化Vue項(xiàng)目下的項(xiàng)目結(jié)構(gòu)
這篇文章主要介紹了詳解使用vue-cli腳手架初始化Vue項(xiàng)目下的項(xiàng)目結(jié)構(gòu),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03

