在 vue
中通过 element-plus 库的 el-upload
实现文件上传。
一、请求
axios({
url: '#',
headers: {
'Content-Type': 'multipart/form-data'
},
method: 'post',
data: {
} // 需要上传的文件内容
})
以 axios
请求为例,对于文件上传的接口,上传的请求类型必须是 multipart/form-data
,上传的内容不再是 json
格式,而是一个文件类型。data
参数是用于传入文件。
二、HTML
1.我这边是把上传文件放在一个 el-dialog
弹框中,打开弹框再把文件传入,再点击确定进行上传。
2.如果不需要弹框,自行把弹框的步骤忽略就好。
3.如果要实现文件传入后不需要点击按钮自动上传,请自行设置 action
或者看其他文章,这篇文章参考意义不大。
<!-- 导入 -->
<el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
<el-upload
ref="importRef"
:limit="1"
action="#"
accept=".xlsx, .xls"
:on-remove="(file, fileList) => {removeImportFile(file, fileList)}"
:on-change="(file, fileList) => (changeImportFile(file, fileList))"
:on-exceed="exceedImportFile"
:auto-upload="false"
drag
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</template>
</el-dialog>
el-upload
部分属性的意义:
- ref:方便在vue中获取DOM节点
- limit:限制一次上传文件的数量,这里每次只能上传一个文件,实现多个文件上传的话自行在文件获取和接口上传那边修改下
- action:请求URL,我这里是手动用按钮请求上传,而不是通过组件本身的action传入文件后自动上传,所以这部分没用,可以删掉,也可以像我一样传个#
- accept:接受上传的文件类型(thumbnail-mode 模式下此参数无效),我这边比较懒类型判断就用组件本身自带的了,其实可以在传入文件的时候自行判断文件类型,我这边是没做处理的,这样简单点,文件大小什么的也没做控制
- on-remove:文件列表移除文件时的钩子
- on-change:文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
- on-exceed:当超出限制时,执行的钩子函数
- auto-upload:是否自动上传文件
- drag:是否启用拖拽上传
importTemplate()
下载模板的点击事件根据实际需求看不是不是要模板操作,我这边添加了下模板的下载操作,不需要就自行删除。
三、JS
1.我这边用的是vue3,如果不了解的话勉强看下吧,其实和vue2没啥太大区别。
// 导入
const upload = reactive({
// 是否显示弹出层
open: false,
// 弹出层标题
title: ''
})
let fileFormData = reactive(null)
// 监听导入弹框关闭的时候清空列表,防止下次打开文件还在
watch(() => upload.open, () => {
if (!upload.open) {
proxy.$refs.importRef.clearFiles()
fileFormData = null
}
})
// 点击导入按钮,打开弹框
function handleImport () {
upload.open = true
upload.title = '导入'
}
// 移除导入的文件
function removeImportFile (file, fileList) {
proxy.$refs.importRef.clearFiles()
fileFormData = null
}
// 更改导入的文件
function changeImportFile (file, fileList) {
fileFormData = new FormData()
fileFormData.append('file', file.raw)
}
// 上传文件超出个数
function exceedImportFile () {
ElMessage.error('文件个数超出限制,请先移除上一个文件')
}
// 下载导入模板
function importTemplate () {
const a = document.createElement('a')
a.href = '可直接下载的链接,如OSS链接'
a.download = '导入模板.xls'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
// 导入文件上传
function submitFileForm () {
if (fileFormData) {
axios({
url: '#',
headers: {
'Content-Type': 'multipart/form-data'
},
method: 'post',
data: fileFormData // 需要上传的文件内容
}).then(rea => {
upload.open = false
})
}
}
这里文件上传最关键的部分就是通过创建一个FormData
对象,把file文件还是以键值对的形式传递给服务器。