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.pswp.cn/bicheng/78295.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/78295.shtml
英文地址,請注明出處:http://en.pswp.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;下…