el-upload 上传逻辑和ui解耦,上传七牛

解耦的作用在于如果后面要我改成从阿里云oss上传文件,我只需要实现上传逻辑从七牛改成阿里云即可,其他不用动。实现方式有2部分组成,一部分是上传逻辑,一部分是ui。

上传逻辑

大概逻辑就是先去服务端拿上传token和地址,然后用http上传

import { upload } from "@/api/agent-go";
import { isShowErr } from "..";
import axios from "axios";
import { UploadProgressEvent } from "element-plus";export async function uploadFile(file: File,classType: uploadClassType,onUploadProgress?: (progressEvent: UploadProgressEvent) => void
) {if (!file) throw new Error("上传文件失败:缺少file参数");if (!classType) throw new Error("上传文件失败:缺少classType参数");const [res, err] = await upload({fileList: [{ classType, name: file.name }],});if (isShowErr(err) || !res.tokenList[0]) throw new Error("获取token失败");const token = res.tokenList[0];const formData = new FormData();formData.append("file", file);formData.append("token", token.token);formData.append("key", token.key);const config = {headers: { "Content-Type": "multipart/form-data" },onUploadProgress: function (progressEvent) {// 处理上传进度const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);progressEvent.percent = percentCompleted;if (onUploadProgress) onUploadProgress(progressEvent);},};const response = await axios.post(res.addr, formData, config);return response.data.key; // 返回上传的文件key,如果没有response.data.key,则上传失败
}

UI层

关键就是重写http-request用上我们上面写的上传逻辑

<template><el-uploadref="uploadRef"style="width: 100%":before-upload="beforeUpload":http-request="filehandleFileUpload":on-exceed="handleExceed":on-preview="handlePreview":limit="limit"v-model:file-list="fileList"drag><el-icon class="el-icon--upload"><upload-filled /></el-icon><div class="el-upload__text"><em>点击</em>或将文件<em>拖拽</em>到这里上传<div class="el-upload__tip">{{ text }}</div></div><template #tip> </template><ImageViewer ref="imageViewerRef" /></el-upload>
</template><script setup lang="ts">
import { PropType, ref, watch } from "vue";
import { ElMessage, UploadInstance, genFileId } from "element-plus";
import { uploadFile } from "@/utils/upload";
import {UploadRawFile,UploadRequestOptions,UploadUserFile,
} from "element-plus/es/components";
import { isShowErr } from "@/utils";
import { OssFile, download } from "@/api/agent-go";
import { onMounted } from "vue";
import ImageViewer from "@/components/ImageViewer/index.vue";interface UploadOssFile extends UploadRawFile {ossFileData?: OssFile;
}const props = defineProps({ossFileList: {type: Array as PropType<OssFile[]>,default: () => [],},text: {type: String,default: "请上传excel文件",},whiteList: {type: Array as PropType<string[]>,default: () => ["xls", "xlsx"],},classType: {type: String as PropType<uploadClassType>,default: "temp",},limit: {type: Number,default: 1,},
});const uploadRef = ref<UploadInstance>();
const fileList = ref<UploadUserFile[]>([]);watch(() => props.ossFileList,() => {setValue(props.ossFileList);},{immediate: true,}
);function setValue(val: OssFile[]) {fileList.value = val.map((item) => {const file = new File([], item.name) as UploadOssFile;file.ossFileData = item;file.uid = genFileId();return {name: item.name,status: "success",raw: file,};});
}const filehandleFileUpload = async (options: UploadRequestOptions) => {const key = await uploadFile(options.file, props.classType, (e) => {options.onProgress(e);});const params: OssFile = {name: options.file.name,size: options.file.size,classType: props.classType,mimeType: options.file.type,key,};const file = options.file as UploadOssFile;if (file.ossFileData) file.ossFileData.key = key;//ossFilemap.set(options.file.uid, params);return params;
};const handleExceed = (files) => {if (props.limit > 1) {if (fileList.value.length >= props.limit) {ElMessage({type: "error",message: `最多上传${props.limit}个文件, 请删除后再上传`,});return false;}return;}uploadRef.value!.handleRemove(fileList.value[0] as UploadRawFile);const file = files[0] as UploadRawFile;file.uid = genFileId();uploadRef.value!.handleStart(file);uploadRef.value!.submit();
};const imageViewerRef = ref();
const handlePreview = async (file) => {try {const fileSuffix = file.name.substring(file.name.lastIndexOf("."))?.toLowerCase();const isPictures = [".jpg", ".jpeg", ".png", ".gif"].includes(fileSuffix);const [res, err] = await download({fileList: [file.raw.ossFileData as OssFile],method: isPictures ? "default" : "download",});if (isShowErr(err)) return;const map = res.urlMap;const urls = Object.keys(map)?.map((key) => map[key]?.url);if (!urls || urls.length === 0)return ElMessage.error("下载文件失败, 获取不到文件地址");if (isPictures) {imageViewerRef.value.openViewer(0, urls);} else {// 创建一个隐藏的可下载链接const url = urls[0] || "";const link = document.createElement("a");link.href = url;link.setAttribute("download", file.name); // 设置下载后的文件名document.body.appendChild(link);link.click(); // 模拟点击事件触发下载document.body.removeChild(link); // 清理临时元素}} catch (error) {alert("下载文件失败:" + error);}
};const beforeUpload = (file: UploadOssFile) => {//console.log("beforeUpload", file);file.ossFileData = {name: file.name,size: file.size,classType: props.classType,mimeType: file.type,};const isAnyType = props.whiteList.indexOf("*") != -1;const fileSuffix = file.name.substring(file.name.lastIndexOf(".") + 1);const isSuffix = props.whiteList.indexOf(fileSuffix.toLowerCase()) === -1;const isLt = file.size / 1024 / 1024 > 10;let msg;if (isSuffix && !isAnyType) {msg = "上传文件只能是 " + props.whiteList.join(",") + " 格式";}if (isLt) {msg = "上传文件大小不能超过 10MB";}if (msg) {ElMessage({type: "error",message: msg,});return false;}
};function getValue() {const val: OssFile[] = [];let valid = true;fileList.value.forEach((item) => {if (item.status === "uploading" || item.status === "ready") {ElMessage({type: "error",message: "有文件正在上传中,请稍后再试",});valid = false;return;}if (item.status === "fail") {ElMessage({type: "error",message: "有文件上传失败,请重新上传",});valid = false;return;}const file = item.raw as UploadOssFile;if (file.ossFileData) val.push(file.ossFileData);});if (!valid) {throw new Error("文件上传中或上传失败");}return val;
}defineExpose({getValue,
});
</script>
<style lang="scss" scoped></style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/78295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

酒水类目电商代运营公司-品融电商:全域策略驱动品牌长效增长

酒水类目电商代运营公司-品融电商&#xff1a;全域策略驱动品牌长效增长 在竞争日益激烈的酒水市场中&#xff0c;品牌如何快速突围并实现长效增长&#xff1f;品融电商凭借「效品合一 全域增长」方法论与全链路运营能力&#xff0c;成为酒水类目代运营的领跑者。从品牌定位、视…

机器学习特征工程中的数值分箱技术:原理、方法与实例解析

标题&#xff1a;机器学习特征工程中的数值分箱技术&#xff1a;原理、方法与实例解析 摘要&#xff1a; 分箱技术作为机器学习特征工程中的关键环节&#xff0c;通过将数值数据划分为离散区间&#xff0c;能够有效提升模型对非线性关系的捕捉能力&#xff0c;同时增强模型对异…

【MySQL专栏】MySQL数据库的复合查询语句

文章目录 1、首先练习MySQL基本语句的练习①查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J②按照部门号升序而雇员的工资降序排序③使用年薪进行降序排序④显示工资最高的员工的名字和工作岗位⑤显示工资高于平均工资的员工信息⑥显…

Python爬虫(5)静态页面抓取实战:requests库请求头配置与反反爬策略详解

目录 一、背景与需求‌二、静态页面抓取的核心流程‌三、requests库基础与请求头配置‌3.1 安装与基本请求3.2 请求头核心参数解析‌3.3 自定义请求头实战 四、实战案例&#xff1a;抓取豆瓣读书Top250‌1. 目标‌2. 代码实现3. 技术要点‌ 五、高阶技巧与反反爬策略‌5.1 动态…

HTML给图片居中

在不同的布局场景下&#xff0c;让 <img> 元素居中的方法有所不同。下面为你介绍几种常见的居中方式 1. 块级元素下的水平居中 如果 <img> 元素是块级元素&#xff08;可以通过 display: block 设置&#xff09;&#xff0c;可以使用 margin: 0 auto 来实现水平居…

【高频考点精讲】前端构建工具对比:Webpack、Vite、Rollup和Parcel

前端构建工具大乱斗:Webpack、Vite、Rollup和Parcel谁是你的菜? 【初级】前端开发工程师面试100题(一) 【初级】前端开发工程师面试100题(二) 【初级】前端开发工程师的面试100题(速记版) 最近在后台收到不少同学提问:“老李啊,现在前端构建工具这么多,我该选哪个?…

赶紧收藏!教您如何用 GitHub 账号,获取永久免费的 Docker 容器!!快速搭建我们的网站/应用!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 永久免费的 Docker 容器 📒🚀 注册与登录➕ 创建 Docker 容器💻 部署你的网站🔑 注意事项💡 使用场景⚓️ 相关链接 ⚓️📖 介绍 📖 还在为搭建个人网站寻找免费方案而烦恼? 今天发现一个宝藏平台!只需一个 Git…

Java大师成长计划之第3天:Java中的异常处理机制

&#x1f4e2; 友情提示&#xff1a; 本文由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;平台gpt-4o-mini模型辅助创作完成&#xff0c;旨在提供灵感参考与技术分享&#xff0c;文中关键数据、代码与结论建议通过官方渠道验证。 在 Java 编程中&#xff0c;异常处理…

大数据去重

实验4 大数据去重 1.实验目的 通过Hadoop数据去重实验&#xff0c;学生可以掌握准备数据、伪分布式文件系统配置方法&#xff0c;以及在集成开发环境Eclipse中实现Hadoop数据去重方法。 2.实验要求 了解基于Hadoop处理平台的大数据去重过程&#xff0c;理解其主要功能&…

http协议、全站https

一、http协议 1、为何要学http协议? 用户用浏览器访问网页,默认走的都是http协议,所以要深入研究web层,必须掌握http协议 2、什么是http协议 1、全称Hyper Text Transfer Protocol(超文本传输协议) ### 一个请求得到一个响应包 普通…

使用 Logstash 迁移 MongoDB 数据到 Easysearch

大家好&#xff01;在前面的文章中&#xff0c;我们已经详细介绍了如何通过 Logstash 和 Canal 工具实现 MySQL 数据向 Easysearch 的迁移。如果您正在使用 MongoDB 作为数据存储&#xff0c;并希望将其数据迁移到 Easysearch 中&#xff0c;这篇指南或许能为您提供一些帮助。 …

亚马逊英国站FBA费用重构:轻小商品迎红利期,跨境卖家如何抢占先机?

一、政策背景&#xff1a;成本优化成平台与卖家共同诉求 2024年4月&#xff0c;亚马逊英国站&#xff08;Amazon.co.uk&#xff09;发布近三年来力度最大的FBA费用调整方案&#xff0c;标志着英国电商市场正式进入精细化成本管理时代。这一决策背后&#xff0c;是多重因素的叠…

使用Qt Quick Controls创建自定义日历组件

目录 引言相关阅读1. DayOfWeekRow2. MonthGrid3. WeekNumberColumn 项目结构及实现工程结构图代码实现及解析1. 组件封装2. 主界面实现 运行效果 总结下载链接 引言 Qt6 Quick框架提供了一套丰富的日历相关组件&#xff0c;包括 MonthGrid、DayOfWeekRow 和 WeekNumberColumn…

【AI微信小程序开发】大转盘小程序项目代码:自设转盘选项和概率(含完整前端+后端代码)

系列文章目录 【AI微信小程序开发】AI减脂菜谱小程序项目代码:根据用户身高/体重等信息定制菜谱(含完整前端+后端代码)【AI微信小程序开发】AI菜谱推荐小程序项目代码:根据剩余食材智能生成菜谱(含完整前端+后端代码)【AI微信小程序开发】图片工具小程序项目代码:图片压…

redis相关问题整理

Redis 支持多种数据类型&#xff1a; 字符串 示例&#xff1a;存储用户信息 // 假设我们使用 redis-plus-plus 客户端库 auto redis Redis("tcp://127.0.0.1:6379"); redis.set("user:1000", "{name: John Doe, email: john.doeexample.com}"…

Vue-组件的懒加载,按需加载

在Vue项目中实现组件的懒加载&#xff08;也称为按需加载或代码分割&#xff09;&#xff0c;可以大大提升应用的加载速度和性能。懒加载主要通过Webpack的代码分割功能实现&#xff0c;特别是使用动态导入&#xff08;import()语法&#xff09;。 为什么要使用懒加载&#xf…

C# new Bitmap(32043, 32043, PixelFormat.Format32bppArgb)报错:参数无效,如何将图像分块化处理?

C#处理非常大的图像&#xff08;如 32043x32043 像素&#xff09;时&#xff0c;确实需要采取分块化处理的方法来避免内存不足的问题。分块化处理可以将大图像分割成多个较小的块&#xff0c;分别进行处理和保存&#xff0c;最后再合并这些块以形成完整的图像。以下是一个详细的…

如何使用极狐GitLab 的外部状态检查功能?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 外部状态检查 (ULTIMATE ALL) pending 状态引入于极狐GitLab 16.5 pending 状态检查的超时时间为两分钟引入于极狐GitLab 16…

深入探索Spark-Streaming:从Kafka数据源创建DStream

在大数据处理领域&#xff0c;Spark-Streaming是一个强大的实时流处理框架&#xff0c;而Kafka作为高性能的分布式消息队列&#xff0c;二者结合能实现高效的数据处理。今天就来聊聊Spark-Streaming中从Kafka数据源创建DStream的相关知识。 早期&#xff0c;Spark-Streaming通过…

Kafka 详解

1.基本概念&#xff1a;Kafka 是分布式发布 - 订阅消息系统&#xff0c;具有高吞吐量、可扩展性等优势&#xff0c;支持点对点和发布订阅两种消息模式&#xff0c;涉及 Broker、Topic、Partition 等多种角色。 2.安装步骤&#xff1a;需先安装 JDK 和 Zookeeper&#xff0c;下…