<el-uploadclass="uploadDemo":limit="1"dragaccept=".xls,.xlsx" <!-- 只保留Excel格式 -->:on-exceed="handleExceedFileLimit":on-change="handleChangeExcelFile":on-remove="handleRemoveExcelFile":before-remove="beforeRemoveFile":file-list="uploadExcelFileList":auto-upload="false"action=""
><i class="el-icon-upload"></i><center><div class="el-upload__text">将文件拖到此处,或<em>点击上传文件</em></div><div slot="tip" class="el-upload__tip">支持上传EXCEL文件(.xls,.xlsx)<br />一次只允许上传一个文件且文件大小不超过{{ maxFileSize }}MB)</div></center>
</el-upload>
<div><el-buttontype="primary"v-show="uploadExcelFileList.length > 0"@click="confirmExcelUpload">上传</el-button>
</div>
(1)限制只能上传 Excel 类型文件
修改accept属性的值(accept=".pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx"
),只保留 Excel 相关的文件格式。
同时,在handleChangeExcelFile
方法中添加类型验证(以 Vue 为例):
methods: {handleChangeExcelFile(file, fileList) {// 获取文件后缀名const fileName = file.name;const suffix = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();// 验证文件类型if (suffix !== '.xls' && suffix !== '.xlsx') {this.$message.error('请上传Excel格式的文件(.xls或.xlsx)');// 从文件列表中移除不符合要求的文件this.uploadExcelFileList = fileList.filter(item => item.uid !== file.uid);return false;}// 后续的处理逻辑...}
}
①accept属性在文件选择对话框层面就过滤掉非 Excel 文件;
②代码中的二次验证可以防止用户通过修改文件后缀名绕过限制;
(2)el-upload组件属性
- :
on-exceed="handleExceedFileLimit"
作用:当上传的文件数量超过 limit 限制时触发的回调函数。
场景:例如设置了 :limit=“1”(最多传 1 个文件),当用户尝试上传第 2 个文件时触发。
参数:接收两个参数files
(超出的文件列表)和fileList
(当前所有文件列表)。
/*** 图片超出个数限制*/
handleExceedFileLimit() {this.$message.error('已超出最大文件个数');
},
- :
on-change="handleChangeExcelFile"
作用:文件状态发生变化时触发(包括文件选择、上传成功 / 失败、进度更新等)。
场景:选择文件后、文件上传中、上传完成(成功 / 失败)等时机都会触发。
参数:接收三个参数 file(当前操作的文件对象)、fileList(当前所有文件列表)、event(原生事件)。
典型用途:
①验证文件类型 / 大小
②更新上传进度显示
③处理上传成功 / 失败的逻辑
/*** 文件状态发生改变时触发*/
handleChangeExcelFile(file, fileList) {// 获取文件后缀名const fileName = file.name;const suffix = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();// 验证文件类型if (suffix !== '.xls' && suffix !== '.xlsx') {this.$message.error('请上传Excel格式的文件(.xls或.xlsx)');// 从文件列表中移除不符合要求的文件this.uploadExcelFileList = fileList.filter(item => item.uid !== file.uid);return false;}// 添加文件this.uploadExcelFileList.push(file);
},
- :
on-remove="handleRemoveExcelFile"
作用:文件被成功删除后触发的回调函数。
场景:用户删除已选中 / 上传的文件,且通过了 before-remove 验证后触发。
参数:接收两个参数 file(被删除的文件对象)和 fileList(删除后的文件列表)。
典型用途:
①同步更新本地文件列表数据
②向后端发送删除文件的请求(如果文件已上传)
/*** 删除文件*/
handleRemoveExcelFile(file, fileList) {this.uploadExcelFileList = [];
},
:before-remove="beforeRemoveFile"
作用:删除文件前触发的回调函数,用于确认是否允许删除。
场景:用户点击删除按钮时,先执行此方法,再决定是否执行删除操作。
参数:接收两个参数 file(要删除的文件对象)和 fileList(当前所有文件列表)。
特殊说明:
①返回 true 或 Promise resolve 时,允许删除
②返回 false 或 Promise reject 时,阻止删除
/*** 删除文件之前的钩子,参数为上传的文件和文件列表,* 若返回 false 或者返回 Promise 且被 reject,则停止删除。* @param file 移除的图片* @param fileList 图片列表*/
beforeRemoveFile(file, fileList) {return this.$confirm(`确定移除 ${file.name}?`);
},
(3)FormData 对象构建表单数据
FormData
对象,用于构建表单数据,专门用于在客户端(浏览器)向服务器发送文件、键值对等数据,尤其适合文件上传场景。
①数据容器:FormData
就像一个 “虚拟表单”,可以通过 append()
方法添加各种数据(字符串、数字、文件等)。
②适配文件上传:由于要上传 Excel 文件(二进制数据),普通的 JSON
格式无法处理二进制数据,而 FormData
是浏览器原生支持的、专门用于传输二进制数据(如文件)
和键值对
的格式,能完美适配文件上传场景。
③与请求配合:通过 this.$request.post(url, formData)
发送请求时,浏览器会自动设置正确的请求头(Content-Type: multipart/form-data
),确保服务器能正确解析表单数据(包括文件)。
/*** 文件上传*/
confirmExcelUpload(){this.$confirm('确认上传', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'info'}).then(() => {const loading = this.$loading({lock: true,text: 'Loading',spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.7)'})if(this.yourId!='' && this.myId!=''){if(this.excelTemplateFileData.length > 0){this.$jitsoseVue.MessageWarning('只能上传一个文件')loading.close()}else{let formData = new FormData() //文件表单对象// 检查上传的文件大小是否超过限制if (this.uploadExcelFileList[0].size > this.maxFileSize * 1024 * 1024) {this.uploadExcelFileList = []this.$jitsoseVue.MessageWarning('文件过大,请重新上传')return}formData.append('yourId', this.yourId)formData.append('myId', this.myId)formData.append('file', this.uploadExcelFileList[0].raw)this.loading = true;let url = 'file/insertExcelFile'this.$request.post(url, formData).then(res => {this.$message({type: 'info',message: res.data.obj})this.uploadExcelFileList = []this.getExcelTemplateFile()loading.close()this.loading = false;})}}else{this.$jitsoseVue.MessageWarning('请选择yourId与myId')loading.close()}}).catch(error => {this.$message({type: 'info',message: '已取消上传'})})
},
服务器端接收后,可以通过这些键(yourId、myId、file)获取对应的数据,从而完成文件上传和业务处理。
简单说,formData
在这里就是一个 “数据包”,打包了上传文件和相关业务参数,方便通过 HTTP 请求发送给服务器。
(4)el-upload 组件的文件对象结构
在 Element UI 的 el-upload
组件中,this.uploadExcelFileList[0].raw
中的 .raw
是获取原始文件对象的关键属性,这与组件对文件的处理机制有关:
- el-upload 组件的文件对象结构
当用户选择文件后,el-upload会将文件信息封装成一个组件自定义的文件对象,存入 file-list
绑定的数组(即 uploadExcelFileList
)中。这个对象包含两类信息:
组件自定义的元数据:如 name
(文件名)、size
(文件大小)、uid
(唯一标识)、status
(上传状态)等。
浏览器原生的文件对象:通过 raw
属性暴露,对应 HTML5 中的 File`对象(继承自 Blob)。
- raw原因
原生 File 对象的必要性:
当需要通过 FormData 上传文件、或在前端处理文件内容(如读取 Excel 数据)时,必须使用浏览器原生的 File 对象。因为组件自定义的文件对象只是对文件信息的描述,而非实际可传输 / 可处理的文件数据。
FormData上传的要求:
formData.append('file', 文件对象)
方法要求传入的必须是原生 File
或 Blob
对象,才能正确构建包含文件二进制数据的表单数据。如果直接传入组件的自定义文件对象(而非 .raw),会导致文件数据无法被正确识别和上传。
- 举例说明
如果打印 this.uploadExcelFileList[0],会看到类似结构:
{name: "数据表格.xlsx", // 组件提取的文件名size: 20480, // 组件计算的文件大小(字节)uid: "1629234567890", // 组件生成的唯一标识status: "ready", // 组件标记的状态raw: File { // 原生File对象(关键!)name: "数据表格.xlsx",lastModified: 1629234567890,size: 20480,type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}
}
这里的 raw 才是实际可用于上传的文件数据载体。