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前端實(shí)現(xiàn)驗(yàn)證碼登錄功能
這篇文章主要介紹了vue前端實(shí)現(xiàn)驗(yàn)證碼登錄功能,登錄時(shí)圖形驗(yàn)證通過(guò)三種方法結(jié)合實(shí)例代碼給大家講解的非常詳細(xì), 通過(guò)實(shí)例代碼介紹了vue登錄時(shí)圖形驗(yàn)證碼功能的實(shí)現(xiàn),感興趣的朋友一起看看吧2023-12-12Vue中通過(guò)Vue.extend動(dòng)態(tài)創(chuàng)建實(shí)例的方法
這篇文章主要介紹了Vue中通過(guò)Vue.extend動(dòng)態(tài)創(chuàng)建實(shí)例的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08使用WebStorm用Debug模式調(diào)試Vue等前端項(xiàng)目的步驟
WebStorm提供了更簡(jiǎn)單的前端調(diào)試方法,記錄一下WebStorm調(diào)試步驟啟動(dòng)前端項(xiàng)目,這篇文章主要介紹了使用WebStorm用Debug模式調(diào)試Vue等前端項(xiàng)目的步驟,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-11-11詳解mpvue開(kāi)發(fā)微信小程序基礎(chǔ)知識(shí)
這篇文章主要介紹了詳解mpvue開(kāi)發(fā)微信小程序基礎(chǔ)知識(shí),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Element-ui Drawer抽屜按需引入基礎(chǔ)使用
這篇文章主要為大家介紹了Element-ui Drawer抽屜按需引入基礎(chǔ)使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07關(guān)于element-ui日期時(shí)間選擇器選不中12小時(shí)以后的時(shí)間詳解
在之前做個(gè)一個(gè)組件頁(yè)面中,引用了element-ui組件的日期選擇器,遇到的一個(gè)小問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于element-ui日期時(shí)間選擇器選不中12小時(shí)以后時(shí)間的相關(guān)資料,需要的朋友可以參考下2022-08-08vue實(shí)現(xiàn)前端控制動(dòng)態(tài)路由的示例代碼
本文主要介紹了vue實(shí)現(xiàn)前端控制動(dòng)態(tài)路由的示例代碼,通過(guò)這些步驟,可以有效地根據(jù)用戶權(quán)限動(dòng)態(tài)渲染前端路由,實(shí)現(xiàn)多用戶權(quán)限系統(tǒng),感興趣的可以了解一下2025-04-04