前端 - vue - - elementui上传文件组件封装
场景:
在大多数的后台管理系统开发中 都会有上传文件/图片的操作 后端需要我们传file或者formdata对象 我们可以基于elementui的upload控件实现(大多数ui库的实现原理相同)
elementui的upload控件提供了各种配置 我们需要用到的有 list-type(文件列表表现类型)、file-list(绑定的文件数据)、limit(限制上传个数)、accept(限制上传类型)、before-upload(上传前的回调)、http-request(自定义上传)、on-remove(移除时的回调)、v-loading(加载中效果 看需求而定)【点击跳转至elementui upload控件官方文档】
html:
点击上传 文件类型为 {{ accept }} ,最多上传{{ limit }}个文件 ,且不超过 {{ fileSize }}M (建议图片长为{{ fileDimension[0] }}px, 宽为{{ fileDimension[1] }}px)
js:
// 封装为公共组建的传值配置 props: { // 最大上传数量 limit: { default: () => 1, type: [Number, String], }, // 上传文件\图片 listType: { //text/picture/picture-card type: String, default: () => "text", }, // 上传文件类型 accept: { type: String, }, // 文件大小 单位为M fileSize: [Number, String], // 图片长宽比 如:长2 宽1 及为2 fileDimension: Array, // 动态接口地址 MinioUrl: { default: () => "sport", }, }, data() { return { fileList: [], // 绑定的值 dataList: [], // 处理删除的值 isLoading: false, // 加载效果 }; }, created() {}, computed: { // 动态class 判断是否达到最大个数限制 disabledTwo() { return this.fileList.length this.fileSize * 1024 * 1024) { this.$message.error("文件过大,请重新选择"); return false; } } // 尺寸 可强制限制 也可不限制 // if (this.fileDimension) { // 转base64后获取图片大小 // fileToBaser64(file, (img) => { // const res = (img.width / img.height).toFixed(1); // if (res === this.fileDimension) return false; // }); // } return true; }, // 移除图片 async handleRemove(file) { // 处理未上传图片但数据回显情况 if (!this.dataList.length) this.dataList = this.fileList; const i = this.dataList.findIndex((ele) => ele.url === file.url); const urlArr = this.dataList[i].url.split("/"); // 编辑记录中删除图片需要同步更新记录中存储图片的字段 await removeFileApi( this.MinioUrl, urlArr[urlArr.length - 2] + "/" + urlArr[urlArr.length - 1] ); this.dataList.splice(i, 1); this.fileList.splice(i, 1); // 返回给父组件值 便于进行保存操作 this.$emit("fileUploadChange", this.dataList); }, // 上传 async handleUpload(val) { this.isLoading = true; // 接口要求formdata对象 初始化formdata并添加值 const formdata = new FormData(); formdata.append("file", val.file); try { const { data } = await uploadFileApi(this.MinioUrl, formdata); const fileItem = { uid: val.file.uid, url: data, name: val.file.name, }; // 更新 dataList this.dataList.push(fileItem); // 检查 fileList 中是否已存在相同文件 const isDuplicate = this.fileList.some( (item) => item.uid === fileItem.uid || item.name === fileItem.name ); if (!isDuplicate) { this.fileList.push(fileItem); } // 更新 fileList // this.fileList.push(fileItem); // 通知父组件文件上传变化 this.$emit("fileUploadChange", this.dataList, val.file.name); } catch (error) { console.error("文件上传失败:", error); this.$message.error("文件上传失败,请稍后再试"); } finally { this.isLoading = false; } }, },
获取图片尺寸的方法:
// file转base64 原理就是转为base64渲染在img标签中获取宽高 export const fileToBaser64 = (file, callback) => { var reader = new FileReader(); reader.onload = function (event) { var base64 = event.target.result; var img = document.createElement("img"); img.src = base64; img.onload = function () { callback(img); }; }; reader.readAsDataURL(file); };
css:
// 控制上传按钮隐藏 .noUpload { ::v-deep .el-upload { display: none !important; } ::v-deep .el-upload--picture-card { display: none !important; } }
选择图片后立即上传会有两个问题:
1、用户上传图片后 不保存信息 那么这个图片就会占用服务器资源
2、用户移除图片后 未保存信息并且刷新页面 图片依旧会渲染出来 但根据路径访问图片却访问不到 服务器中也不存在该图片 解决办法:
二者共同的解决方法:
1、后端写定时任务,定时清理服务器中存在但不存在与表中的图片;
2、点击保存按钮后再走上传接口;
此文章只考虑小文件上传 大文件用常规上传方法会很慢导致接口超时 也有可能导致接口奔溃
(图片来源网络,侵删)
(图片来源网络,侵删)
(图片来源网络,侵删)
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。