文件导入导出实现逻辑图:
一、excle文件导出
- 导出员工接口返回的是二进制流
- axios配置responseType为blob接收二进制流文件为Blob格式
- 安装file-saver包,实现下载Blob文件 yarn add file-saver
- 封装导出员工excel的API-代码位置
//excel模板下载接口
export function exportTemplate(){
return request({
url:/cms/userSession/enterprise/enterpriseConfigImportTemplate",
method:'post',
responseType:'blob',// 改变接收数据的类型,使用blob接收二进制文件流
})
}
- 拦截器判断是不是blob类型,如果是直接返回数据,不再进行解构-代码位置(src/utils/request.js)
// 响应拦截器
service.interceptors.response.use((response) => {
// axios默认包裹了data
// 判断是不是Blob
if (response.data instanceof Blob) return response.data // 返回了Blob对象
const { data, message, success } = response.data // 默认json格式
if (success) {
return data
} else {
Message({ type: 'error', message })
return Promise.reject(new Error(message))
}
},
- 安装file-saver
$ npm i file-saver
$ yarn add file-saver
- 点击“下载模版”按钮调用接口,使用file-saver将blob转化成文件下载-代码位置
// 员工下载模版-----------------------
async downloadEmployee() {
const blob = await downloadEmployee()
FileSaver.saveAs(blob, '员工表模版.xlsx')
},
二、excel文件导入
实现逻辑:
- 点击上传按钮,用refs触发type=“file” 的input文件选择事件;input文件选择框隐藏;
- 将input上传的文件参数加入到formData中,调取接口传参;
- 通知父组件跟新页面,关闭弹框,提示上传成功
- 清空input的value值,不然下次无法上传
三、文件拖拽上传
实现逻辑:
- 在需要拖动的dom节点上添加以下属性和事件
- 然后获取拖拽的文件
- 调取封装的上传的方法
@dragover.prevent // 防止事件冒泡
@drop=“handleDrop”
四、完整代码
<template>
<el-dialog
width="500px"
title="员工导入"
:visible="showExcelDialog"
@close="$emit('update:showExcelDialog', false)"
>
<el-row type="flex" justify="center">
<div class="upload-excel">
<input
ref="excel-upload-input"
class="excel-upload-input"
type="file"
accept=".xlsx, .xls"
@change="selectFile"
>
<div
class="drop"
@dragover.prevent
@drop="handleDrop"
>
<i class="el-icon-upload" />
<el-button type="text" @click="downloadEmployee">下载导入模板</el-button>
<span>将文件拖到此处或
<el-button type="text" @click="uploadExcel">点击上传</el-button>
</span>
</div>
</div>
</el-row>
<el-row type="flex" justify="end">
<!-- update:props属性名,值 直接修改 .sync修饰符的属性值 -->
<el-button size="mini" type="primary" @click="$emit('update:showExcelDialog', false)">取消</el-button>
</el-row>
</el-dialog>
</template>
<script>
import { downloadEmployee, UploadExcel } from '@/api/employee'
import FileSaver from 'file-saver'
export default {
props: {
showExcelDialog: {
type: Boolean,
default: true
}
},
methods: {
// 员工下载模版-----------------------
async downloadEmployee() {
const blob = await downloadEmployee()
console.log(1111, blob)
FileSaver.saveAs(blob, '员工表模版.xlsx')
},
// 上传excel文件--------------------------
uploadExcel() {
this.$refs['excel-upload-input'].click()
},
// 点击文件选择-------------------------------
selectFile(e) {
// 获取选择的文件列表
const files = e.target.files
if (files.length > 0) {
this.uploadFiles(files[0])
}
// 判断是否选择了文件,上传第一个文件
// if (files.length > 0) {
// const fd = new FormData()
// fd.append('file', files[0])
// try {
// await UploadExcel(fd)
// // 通知父组件
// this.$emit('uploadSuccess')
// this.$emit('update:showExcelDialog', false)
// this.$message.success('上传成功')
// } catch (error) {
// // 清空文件选择器
// // this.$refs['excel-upload-input'].value = ''
// } finally {
// // 无论成功还是失败都会来到这里执行清空选择器
// this.$refs['excel-upload-input'].value = ''
// }
// }
},
// 选择了文件后上传的方法,两处都用到了,所以封装了方法
async uploadFiles(file) {
const fd = new FormData()
fd.append('file', file)
try {
await UploadExcel(fd)
// 通知父组件
this.$emit('uploadSuccess')
this.$emit('update:showExcelDialog', false)
this.$message.success('上传成功')
} catch (error) {
// 清空文件选择器
// this.$refs['excel-upload-input'].value = ''
} finally {
// 无论成功还是失败都会来到这里执行清空选择器
this.$refs['excel-upload-input'].value = ''
}
},
// 拖拽文件选择
handleDrop(event) {
event.preventDefault()
const files = event.dataTransfer.files
if (files.length > 0) {
this.uploadFiles(files[0])
}
}
}
}
</script>
<style scoped lang="scss">
.upload-excel {
display: flex;
justify-content: center;
margin: 20px;
width: 360px;
height: 180px;
align-items: center;
color: #697086;
.excel-upload-input {
display: none;
z-index: -9999;
}
.btn-upload,
.drop {
border: 1px dashed #dcdfe6;
width: 100%;
height: 100%;
text-align: center;
line-height: 160px;
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: center;
}
.drop {
line-height: 40px;
color: #bbb;
i {
font-size: 60px;
display: block;
color: #c0c4cc;
}
}
}
</style>