官网:https://element-plus.gitee.io/zh-CN/component/upload.html
单个文件上传
<template>
<el-upload
ref="upload"
action=" /object/radr/ballistic/localBallisticConvert"
:data="uploadData"
:before-upload="(file)=>{
beforeUpload(file)
}"
:show-file-list="false"
accept=".json"
>
<el-button
type="primary"
:disabled="isAction"
>
加载文件2
</el-button>
</el-upload>
</template>
<script lang="ts" setup>
import {
ref } from 'vue'
import type {
UploadInstance } from 'element-plus'
const uploadData = ref({
file:null,
latitude:null,
launchDirection:null,
localBallistic:null,
longitude:null,
});
const fileName = ref()
function beforeUpload(file){
fileName.value = file.name,
uploadData.value.file= file
}
</script>
多文件上传
在ElementPlus中有手动上传的方法,具体实现是点击手动上传后,将多个文件进行单个上传,会触发多次请求
<template>
<el-upload
ref="uploadRef"
class="upload-demo"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
:auto-upload="false"
>
<template #trigger>
<el-button type="primary">select file</el-button>
</template>
<el-button class="ml-3" type="success" @click="submitUpload">
upload to server
</el-button>
<template #tip>
<div class="el-upload__tip">
jpg/png files with a size less than 500kb
</div>
</template>
</el-upload>
</template>
<script lang="ts" setup>
import {
ref } from 'vue'
import type {
UploadInstance } from 'element-plus'
const uploadRef = ref<UploadInstance>()
const submitUpload = () => {
uploadRef.value!.submit()
}
</script>
action="https://run.mocky.io"
请求 URLheaders
设置上传的请求头部method
设置上传请求方法multiple
是否支持多选文件data
上传时附带的额外参数name
上传的文件字段名with-credentials
支持发送 cookie 凭证信息 boolean falseshow-file-list
是否显示已上传文件列表 boolean truedrag
是否启用拖拽上传 boolean falseaccept
接受上传的文件类型(thumbnail-mode 模式下此参数无效) stringon-preview
点击文件列表中已上传的文件时的钩子 (uploadFile: UploadFile) => voidon-remove
文件列表移除文件时的钩子 (uploadFile: UploadFile, uploadFiles: UploadFiles) => voidon-success
文件上传成功时的钩子 (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => voidon-error
文件上传失败时的钩子 (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) => voidon-progress
文件上传时的钩子 (evt: UploadProgressEvent, uploadFile: UploadFile, uploadFiles: UploadFiles) => voidon-change
文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 (uploadFile: UploadFile, uploadFiles: UploadFiles) => voidon-exceed
当超出限制时,执行的钩子函数 (files: File[], uploadFiles: UploadFiles) => void —before-upload
上传文件之前的钩子,参数为上传的文件, 若返回false或者返回 Promise 且被 reject,则停止上传。 (rawFile: UploadRawFile) => Awaitablebefore-remove
删除文件之前的钩子,参数为上传的文件和文件列表, 若返回 false 或者返回 Promise 且被 reject,则停止删除。 (uploadFile: UploadFile, uploadFiles: UploadFiles) => Awaitablefile-list / v-model:file-list
默认上传文件 UploadUserFile[] []list-type
文件列表的类型 'text' | 'picture' | 'picture-card' 'text'auto-upload
是否自动上传文件 boolean truehttp-request
覆盖默认的 Xhr 行为,允许自行实现上传文件的请求 (options: UploadRequestOptions) => XMLHttpRequest | Promise —disabled
是否禁用上传 boolean falselimit
允许上传文件的最大数量 number
1、我的思路
- 需求
- 想要将多个文件一起上传【备注:多个按钮上传多个文件,然后一起提交】
问题
预期效果
在提交之后默认将文件格式转换成了
[object File]
,而不是(binary),因此使用单个文件单个上传
思路
- 使用上传文件之前的钩子
before-upload
,在第一个文件要上传时返回false停止上传 - 在第二个按钮点击上传时将上传文件之前的钩子
before-upload
的返回值为true,开始上传。
- 使用上传文件之前的钩子
- HTML
<el-upload ref="upload" action=" /object/radr/ballistic/localBallisticConvert" :data="uploadData" :before-upload="(file)=>{ return beforeUpload(file,'file1') }" :show-file-list="false" accept=".txt" > <el-button :disabled="isAction" > 加载文件1 </el-button> </el-upload> <el-upload ref="upload" action=" /object/radr/ballistic/localBallisticConvert" :data="uploadData" :before-upload="(file)=>{ beforeUpload(file,'file2') }" :show-file-list="false" accept=".json" > <el-button type="primary" :disabled="isAction" > 加载文件2 </el-button> </el-upload>
- JS
function beforeUpload(file,FLAG){ if(FLAG ==='file1'){ fileName.value.file1Name = file.name, uploadData.value.file1= file } if(FLAG === 'file2'){ fileName.value.file2Name = file.name, uploadData.value.file2= file } return FLAG === 'file2' ? true :false }
2、优化思路一
在网上搜索多篇文章之后,继续优化了我的思路
这里不通过submit去提交,通过自己定义方法提交需要用到new FormData()
对象,不了解FormData
的朋友可以点击这里 FormData
,用element
自带的on-change
和on-remove
可以很方便获取到fileList
,最后把获取到的formData
在通过接口传递即可
引用来自:https://blog.csdn.net/wangyile4399/article/details/111315799
HTML
<template> <el-upload class="pop-upload" ref="upload" action="" :file-list="fileList" :auto-upload="false" :multiple="true" :on-change="handleChange" :on-remove="handleRemove" > <el-button slot="trigger" size="small" type="primary">选取文件</el-button> <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button> </el-upload> </template>
- 参数信息
- action参数必填,这里不走el-upload的默认上传,所以用不到这个地址,填空即可,因为是用自己封装方法提交,所以用不到on-success和on-error方法。
JS
<script> import request from "@/utils/request" // 此处为请求的封装方法,没有引用可以忽略 export default { data() { return { fileList: [], // 定义一个空数组 }; }, methods: { // 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用,function(file, fileList) handleChange(file, fileList) { this.fileList = fileList }, // 删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。function(file, fileList) handleRemove(file, fileList) { this.fileList = fileList }, //上传服务器 submitUpload() { //判断是否有文件再上传 if (this.fileList.length === 0) { return this.$message.warning('请选取文件后再上传') } // 下面的代码将创建一个空的FormData对象: const formData = new FormData() // 你可以使用FormData.append来添加键/值对到表单里面; this.fileList.forEach((file) => { formData.append('file', file.raw) }) // 添加自定义参数,不传可删除 formData.append('parentId', '49') formData.append('uploadType', '备料单') formData.append('versions', 'v4.0') //自定义的接口也可以用ajax或者自己封装的接口 request({ method: 'POST', url: '/uploadFile', //填写自己的接口 data: formData //填写包装好的formData对象 }).then(res => { if (res.data.code == 200) { this.$message.success('上传成功'); } else { this.$message.error('上传失败'); } //清空fileList this.fileList = [] }) }, }, }; </script>
3、优化思路二
控制判断文件个数是否等于 fileList 的长度是否相等,相等再上传。
引用来自:https://blog.csdn.net/qq_36022463/article/details/122723998- HTML
- JS
每次选择文件的时候设置为0 ,将最初的fileList存起来
不然每一个文件都会执行on-change,都会初始化fileList,就不能根据fileList判断是否有这个文件
3、优化思路三
借助FormData的格式向后台传文件组
- HTML
```html
<div class="upload-file">
<el-upload
accept=".xlsx"
ref="upload"
multiple
:limit="5"
action="http://xxx.xxx.xxx/personality/uploadExcel"
:on-preview="handlePreview"
:on-change="handleChange"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:file-list="fileList"
:http-request="uploadFile"
:auto-upload="false">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 133px;" size="small" type="success" @click="submitUpload">上传到服务器
</el-button>
<div slot="tip" class="el-upload__tip">只能上传xlsx文件,且不超过100m</div>
</el-upload>
</div>
```
修改:auto-upload="false"属性为false,阻止组件的自动上传
:http-request="uploadFile"覆盖上传事件
@click=“submitUpload”,给上传按钮绑定事件JS
```js
data() {return { fileData: '', // 文件上传数据(多文件合一) fileList: [], // upload多文件数组 uploadData: { fieldData: { id: '', // 机构id, } }, }
}
methods:{
// 上传文件
uploadFile(file) {
this.fileData.append('files', file.file); // append增加数据
},
// 上传到服务器
submitUpload() {
let fieldData = this.uploadData.fieldData; // 缓存,注意,fieldData不要与fileData看混
if (fieldData.id === '') {
this.$message({
message: '请选择上传机构',
type: 'warning'
})
} else if (this.fileList.length === 0) {
this.$message({
message: '请先选择文件',
type: 'warning'
})
} else {
const isLt100M = this.fileList.every(file => file.size / 1024 / 1024 < 100);
if (!isLt100M) {
this.$message.error('请检查,上传文件大小不能超过100MB!');
} else {
this.fileData = new FormData(); // new formData对象
this.$refs.upload.submit(); // 提交调用uploadFile函数
this.fileData.append('pathId', fieldData.id); // 添加机构id
this.fileData.append('loginToken', this.loginToken); // 添加token
post(this.baseUrlData.url_02 + ":8090/personality/uploadExcel", this.fileData).then((response) => {
if (response.data.code === 0) {
this.$message({
message: "上传成功",
type: 'success'
});
this.fileList = [];
} else {
this.$message({
message: response.data.desc,
type: 'error'
})
}
});
}
}
},
//移除
handleRemove(file, fileList) {
this.fileList = fileList;
// return this.$confirm(`确定移除 ${ file.name }?`);
},
// 选取文件超过数量提示
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 5 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
},
//监控上传文件列表
handleChange(file, fileList) {
let existFile = fileList.slice(0, fileList.length - 1).find(f => f.name === file.name);
if (existFile) {
this.$message.error('当前文件已经存在!');
fileList.pop();
}
this.fileList = fileList;
},
}
```
- 案例
原生js实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.file {
position: relative;
display: inline-block;
background: #133d63;
border: 0.1rem solid #99d3f5;
border-radius: 0.2rem;
padding: 0.2rem 0.6rem;
overflow: hidden;
color: #f0faff;
text-decoration: none;
text-indent: 0;
line-height: 1.5rem;
font-size: 0.8rem;
margin-left: 7rem;
}
.file input {
position: absolute;
font-size: 0.8rem;
right: 0;
top: 0;
opacity: 0;
cursor: pointer;
}
.file:hover {
background: #aadffd;
border-color: #78c3f3;
color: #004974;
text-decoration: none;
}
</style>
</head>
<body>
<div class="file">
上传文件
<input type="file" name="image" accept="image/*" onchange="upload()">
</div>
<script type="text/javascript">
function upload (event) {
var e = window.event || event;
console.log(e)
// 获取当前选中的文件
var File = e.target.files[0];
console.log(File);//打印值看下面图片,简单点的话我们直接把这个数据给后台处理就可以了
var data = new FormData();
data.append("file", File)
let refreshToken = localStorage.getItem("token");
axios
.post(
"http://202.101.162.69:8089/proxy/top/api/upload/oss",
data,
{
headers: {
Authorization: refreshToken,
},
}
)
.then((res) => {
if (res.data.code == 200) {
this.$message({
message: "上传文件成功",
type: "success",
center: "true",
duration: 500,
customClass: "press",
});
} else {
this.$message({
message: "上传文件失败",
type: "warning",
center: "true",
duration: 500,
customClass: "press",
});
}
})
}
</script>
</body>
</html>