实现图片上传功能
下面是基于element-plus官方提供的一个上传图片的组件:
xml
<template>
<el-upload list-type="picture-card" :auto-upload="false" multiple :on-change="handleChange">
<el-icon><Plus /></el-icon>
<template #file="{ file }">
<div>
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<el-icon><zoom-in /></el-icon>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownload(file)">
<el-icon><Download /></el-icon>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
</template>
</el-upload>
<el-button @click="handleSuccess">点击上传</el-button>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { userUplodImg } from '@/api/user'; // 上传文件的接口地址(如果没有可以发起原生的axios)
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const disabled = ref(false);
const fileList = ref([]); // 存放图片列表
// 删除操作逻辑
const handleRemove = (file) => {
console.log(file);
};
const handlePictureCardPreview = (file) => {
dialogImageUrl.value = file.url;
dialogVisible.value = true;
};
const handleDownload = (file) => {
console.log(file);
};
// 文件修改
const handleChange = (file, newFileList) => {
fileList.value = [...newFileList];
};
// 自定义上传行为
const handleSuccess = async () => {
const formData = new FormData();
fileList.value.forEach((file) => {
formData.append('files[]', file.raw); // 添加文件到FormData
});
const res = await userUplodImg(formData);
fileList.value = [];
console.log(fileList.value);
console.log('上传放回的结果:', res);
};
// 如果您没有写接口,可以使用下面的方式发起原生的axios请求
自定义上传行为;
const uploadFiles = async (uploadData) => {
const formData = new FormData();
fileList.value.forEach((file) => {
formData.append('files', file.raw); // 添加文件到FormData
});
try {
const response = await axios.post('接口地址', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
// 调用成功回调函数
uploadData.onSuccess(response.data);
fileList.value = [];
} catch (error) {
// 调用失败回调函数
uploadData.onError(error);
}
};
</script>
想要实现我们需要了解下面提供的一些属性:
- action:请求的url
(因为我们是自定义长传请求,所以不需要设置)
- multiple:是否支持多选文件 默认值是false
- show-file-list:是否显示已上传文件列表
- on-success:文件上传时候的钩子
注意使用这个函数有一个陷阱,那就是我们在选择多选文件的时候这这个钩子会触发多次。这样就没办法实现我们多个文件调用一次接口。所以我们这篇王文章就不使用这个钩子函数
- on-change:文件状态改变时候的钩子,添加文件、上传成功和上传失败时都会被调用
这个函数有两个参数,一个是file另一个是fileList
fileList
这是一个上传文件列表,类型为数组。每个文件都是一个对象,包含文件的属性,如文件名、大小、类型等。在用户选择文件并上传时,会将文件添加到 fileList 数组中。在回调函数中,可以通过 fileList 数组来获取当前上传文件列表的信息。例如,通过 fileList[0].name 可以获取第一个文件的文件名,通过 fileList[1].size 可以获取第二个文件的文件大小。
file
它代表当前操作的文件,类型为对象。每当用户上传文件或删除文件时,file 参数都会更新为当前操作文件的信息。在回调函数中,可以通过 file 对象来获取当前操作文件的信息。例如,在上传文件时,可以通过 file.name 获取正在上传的文件的文件名,在删除文件时,可以通过 file.response 获取服务器响应的信息。
6.list-type:文件列表的类型取值为'text' | 'picture' | 'picture-card'
(我们需要将取值设置为picture-card)
- http-request:覆盖默认的 Xhr 行为,允许自行实现上传文件的请求
(因为我们要实现的是多个文件一次提交。所以这个也用不上,如果一次提交一个文件,可以使用)
下面是对这个代码的解释:
- 当触发
handleChange
函数的时候我们需要将第二个代表文件列表的数据存放起来,为了一次发多个文件请求做准备 - 点击文件上传的时候需要我们遍历存放的文件列表,创建一个
FormData数据类型
,将待上传的文件列表(flie.raw)
追加到新建的formdata数据类型中,在点击发送即可 在 Element UI 的上传组件 el-upload 中,fileList.raw 是一个属性,它是一个数组,包含所有已经上传的文件对象,即原始文件对象,不包含任何处理或转换
。每个文件对象都包含文件的原始属性,如文件名、大小、类型等。通常情况下,fileList 中的文件对象会在上传之前经过一些处理,例如压缩、裁剪、格式转换等,这些处理会生成新的文件对象,并存放在 fileList 中。而 fileList.raw 则是保存了未经过处理的原始文件对象的数组。 使用 fileList.raw 可以方便地访问原始文件对象的属性,进行一些特殊的处理或获取更具体的信息- 如果你没有设置接口函数,也可以直接发起原生的axios请求
js
//自定义上传行为;
const uploadFiles = async (uploadData) => {
const formData = new FormData();
fileList.value.forEach((file) => {
formData.append('files', file.raw); // 添加文件到FormData
});
try {
const response = await axios.post('接口地址', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
// 调用成功回调函数
uploadData.onSuccess(response.data);
fileList.value = [];
} catch (error) {
// 调用失败回调函数
uploadData.onError(error);
}
};
注意这里面的一些坑
- 因为我们需要实现的是多个文件一次上传请求一次接口,所以就得自己实现请求接口的操作,而一次上传一个文件就不需要。
- 网上有的博主在on-change函数中使用了变量进行控制,这样确实可以使on-change只触发一次,但是每次上传的文件就没办法多选。
- 当使用
el-upload
组件上传多个文件时,每个文件会触发一次上传请求。所以就不能让组件自动的发送请求,就需要我们进行控制 - 还有一种博主在说可以
判断上传文件的数组长度,根据长度达到条件在进行相应的发送请求逻辑
,这用方法确实可以实现,但是当我们再次上传的时候,上传接口就失效了。