【篇三】在vue3上实现阿里云oss文件直传

之前写了两篇关于文件上传的文章
【篇一】使用springboot+vue实现阿里云oss上传
【篇二】使用springboot+vue实现阿里云oss文件直传,解决大文件分片上传问题
今天介绍一下在vue3中实现阿里云oss文件直传,主要是基于篇二中的源码进行修改,看具体代码

OssFileUpload组件

<template><div class="upload-file"><el-upload:multiple="multiple":accept="accept.join(',')"action="#":http-request="handleUpload":before-upload="handleBeforeUpload":file-list="fileList":limit="limit":on-exceed="handleExceed":show-file-list="false":data="data"class="upload-file-uploader"ref="fileUpload"><!-- 上传按钮 --><el-button type="primary">选取文件</el-button><template v-if="multiple"> (按住Ctrl键多选)</template></el-upload><!-- 上传提示 --><div class="el-upload__tip" slot="tip" v-if="showTip && fileList.length<=0"><span v-if="limit"> 1、文件数量限制为 <b style="color: #f56c6c">{{ limit }}个</b></span><span v-if="fileSize"> 2、文件大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b><br></span><span v-if="fileType"> 3、文件格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b><br></span></div><!-- 文件列表 --><transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul" height="485"><li v-for="(file, index) in fileList" :key="file.uid || index " class="el-upload-list__item ele-upload-list__item-content"><el-link :href="file.url" :underline="false" target="_blank"><span class="`el-icon-d`ocument"> {{ file.name }} </span></el-link><div class="ele-upload-list__item-content-action"><el-link :underline="false" @click="handleDelete(index)" type="danger" style="width: 50px">删除</el-link></div></li></transition-group></div>
</template><script setup>
import {handleMD5} from '@/utils/md5';
import {generateOssPolicy} from "@/api/file/file";
import {POST} from "@/utils/request";const props = defineProps({// 是否可多选multiple: {type: Boolean,default: true,},// 值value: [String, Object, Array],// 数量限制limit: {type: Number,default: 5,},// 大小限制(MB)fileSize: {type: Number,default: 5,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ["doc", "xls", "xlsx", "ppt", "txt", "pdf"],},accept: {type: Array,default: () => [".doc", ".xls", ".xlsx", ".ppt", ".txt", ".pdf"],},// 是否显示提示isShowTip: {type: Boolean,default: true},// 是否重命名rename: {type: Boolean,default: true}
});const {proxy} = getCurrentInstance();
const emit = defineEmits();
const number = ref(0);
const uploadList = ref([]);
const fileList = ref([]);
const data = ref({});
const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize)
);
watch(() => [props.value, props.rename], ([val1, val2]) => {if (val1) {let temp = 1;// 首先将值转为数组const list = Array.isArray(val1) ? val1 : props.value.split(',');// 然后将数组转为对象数组fileList.value = list.map(item => {if (typeof item === "string") {item = {name: item.name, url: item.url};}item.uid = item.uid || new Date().getTime() + temp++;return item;});} else {fileList.value = [];return [];}if (val2) {data.value = {rename: val2}}
}, {deep: true, immediate: true});// 上传前校检格式和大小
function handleBeforeUpload(file) {// 校检文件类型if (props.fileType) {const fileName = file.name.split('.');const fileExt = fileName[fileName.length - 1];const isTypeOk = props.fileType.indexOf(fileExt) >= 0;if (!isTypeOk) {proxy.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);return false;}}// 校检文件大小if (props.fileSize) {const isLt = file.size / 1024 / 1024 < props.fileSize;if (!isLt) {proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);return false;}}//增加判断逻辑:如果是视频文件,获取视频分辨率const isVideo = file.type === "video/mp4" || file.type === "video/webm";if (isVideo) {// 创建一个视频元素const video = document.createElement('video');video.preload = 'metadata';// 设置视频源video.src = URL.createObjectURL(file);// 监听加载元数据完成video.onloadedmetadata = () => {URL.revokeObjectURL(video.src); // 释放URL对象const width = video.videoWidth;const height = video.videoHeight;// 获取视频时长const duration = video.duration;file.width = width;file.height = height;file.duration = duration;// 这里可以根据分辨率做进一步处理,例如检查分辨率是否符合要求};}proxy.$modal.loading("正在上传文件,请稍候...");number.value++;return true;
}// 文件个数超出
function handleExceed() {proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
}// 删除文件
function handleDelete(index) {fileList.value.splice(index, 1);emit("update:value", listToString(fileList.value));
}// 上传结束处理
function uploadedSuccessfully() {if (number.value > 0 && uploadList.value.length === number.value) {fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);uploadList.value = [];number.value = 0;emit("update:value", listToString(fileList.value));proxy.$modal.closeLoading();}
}/** 上传操作 */
function handleUpload(file) {handleMD5(file.file).then(md5 => {const data = {fileName: file.file.name,md5: md5,rename: props.rename// 增加视频的分辨率、播放时长,后端接收后再通过回调接口返回,前端即可获取width: file.file.width,height: file.file.height,duration: file.file.duration,};generateOssPolicy(data).then((response) => {let data = response.datalet formData = new FormData();formData.append('OSSAccessKeyId', data.accessKeyId);formData.append('signature', data.signature);formData.append('policy', data.policy);formData.append('key', data.filePath);formData.append('callback', data.callback);formData.append('success_action_status', 200);formData.append('file', file.file);POST(data.host, formData).then((res) => {let params = res.dataif (params.code !== 200) {proxy.$modal.msgError(params.msg);return;}uploadList.value.push(params.data);uploadedSuccessfully();proxy.$modal.msgSuccess("上传成功");});})})
}// 获取文件名称
function getFileName(name) {if (name.lastIndexOf("/") > -1) {return name.slice(name.lastIndexOf("/") + 1);} else {return "";}
}// 对象转成指定字符串分隔
function listToString(list, separator) {let str = "";separator = separator || ",";for (let i in list) {str += list[i].url + separator;}return str !== '' ? str.substring(0, str.length - 1) : '';
}//暴露给父组件,否则无法获取值
defineExpose({fileList
})
</script><style scoped lang="scss">
.upload-file-uploader {margin-bottom: 5px;
}
.upload-file-list {max-height: 420px;overflow-y: auto;
}
.el-upload__tip span {display: block;width: fit-content;line-height: 20px;
}
.upload-file-list .el-upload-list__item {border: 1px solid #e4e7ed;line-height: 2;margin-bottom: 10px;position: relative;
}
.upload-file-list .ele-upload-list__item-content {display: flex;justify-content: space-between;align-items: center;color: inherit;
}
.ele-upload-list__item-content-action .el-link {margin-right: 10px;
}
</style>

父组件引用

/** 提交按钮 */
function submitForm() {proxy.$refs["editForm"].validate(valid => {if (valid) {// 获取子组件的fileListform.value.files = proxy.$refs.upload.fileListif (!Array.isArray(form.value.files) || form.value.files.length <= 0) {proxy.$alert("请上传文件");return false;}//增加了多个文件属性字段form.value.download = form.value.files[0].urlform.value.name = form.value.files[0].nameform.value.userName = form.value.files[0].userform.value.md5 = form.value.files[0].md5form.value.size = form.value.files[0].sizesave(form.value).then(() => {proxy.$modal.msgSuccess("操作成功");open.value = false;getList();});}});
}

后端代码除组装callbackBody增加了几个参数外,逻辑基本相同,故省略。

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

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

相关文章

机器学习简介--NLP(二)

机器学习简介 机器学习简介机器学习例子机器学习分类有监督学习有监督学习的应用 无监督学习 机器学习常见概念数据集k折交叉验证过拟合欠拟合评价指标 机器学习简介 机器学习例子 问题&#xff1a; 2&#xff0c;4&#xff0c;6&#xff0c;8&#xff0c;&#xff1f;&#…

【CV炼丹师勇闯力扣训练营 Day22:§7 回溯1】

CV炼丹师勇闯力扣训练营 代码随想录算法训练营第22天 回溯法其实就是暴力查找,回溯的本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案&#xff0c;一般可以解决如下几种问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集合切割…

【Laravel生命周期全景】深入框架的心脏

标题&#xff1a;【Laravel生命周期全景】深入框架的心脏 Laravel是一个优雅的PHP Web框架&#xff0c;为现代Web应用程序的开发提供了丰富的功能和清晰的架构。理解Laravel的生命周期对于开发者来说至关重要&#xff0c;因为它涉及到应用程序从启动到响应请求的每一个环节。本…

Ubuntu18.04新安装--无网络连接、重启黑屏解决教程

一、安装Ubuntu Ubuntu安装需要U盘作为启动盘&#xff0c;在目前教新的电脑中选中GPT作为分区&#xff0c;制作启动盘&#xff0c;其中在安装双系统Ubuntu时&#xff0c;以自定义格式作为存储空间。详细安装过程以以及如何分区请参考下列链接&#xff1a;内含详细安装过程&…

VS Code 常用快捷键大全

Visual Studio Code 是目前最好用的代码编辑器之一。它提供了许多开箱即用的功能以及丰富的第三方扩展&#xff0c;本文将分享常用的 VS Code 快捷键&#xff0c;助你提高开发效率&#xff01; 代码导航 跳转指定行&#xff1a;快速跳转到文件中的指定行&#xff0c;只需按下快…

Unity 数据持久化【PlayerPrefs】

1、数据持久化 文章目录 1、数据持久化PlayerPrefs基本方法1、PlayerPrefs概念2、存储相关3、读取相关4、删除数据思考 信息的存储和读取 PlayerPrefs存储位置1、PlayerPrefs存储的数据在哪个位置2、PlayerPrefs 数据唯一性思考 排行榜功能 2、Playerprefs实践1、必备知识点-反…

Java_网络通信:http和https

HTTP&#xff1a; 是互联网上应用最为广泛的一种网络通信协议&#xff0c;基于TCP&#xff0c;可以使浏览器工作更为高效&#xff0c;减少网络传输。 HTTPS&#xff1a; 是HTTP的加强版&#xff0c;可以认为是HTTPSSL(Secure Socket Layer)。在HTTP的基础上增加了一系列的安全…

Apache Flink 任意 JAR 包上传漏洞利用及防范策略

Apache Flink 任意 JAR 包上传漏洞利用及防范策略 引言 Apache Flink 是一个流行的开源流处理框架&#xff0c;由于其强大的流处理能力&#xff0c;被广泛应用于大数据处理领域。然而&#xff0c;近期发现 Apache Flink 1.9.1 版本存在一个严重的安全漏洞&#xff0c;允许攻击…

解决 Layout Inspector无法查看Component Tree 布局层级信息 | Android Studio Koala

问题描述 Tool -> Layout Inspector 显示下图&#xff0c;无法生成.li文件查看Component Tree&#xff0c;变成实时的Preview并功能点击操作&#xff0c;跟模拟器一样。 原因&#xff1a;默认勾选了"Enable embedded Layout Inspector"&#xff0c;启用了嵌入式…

SpringCloud进阶篇

文章目录 网关快速入门创建模块引入依赖修改启动类配置路由路由过滤(一般不用) 自定义GlobalFilter登录校验登录校验过滤器 微服务获取用户信息保存用户信息到请求头拦截器获取用户信息 OpenFeign传递用户信息配置共享添加共享配置拉取共享配置 配置热更新添加配置到Nacos配置热…

数据结构初阶 堆的问题详解(三)

题目一 4.一棵完全二叉树的节点数位为531个&#xff0c;那么这棵树的高度为&#xff08; &#xff09; A 11 B 10 C 8 D 12 我们有最大的节点如下 假设最大高度为10 那么它的最多节点应该是有1023 假设最大高度为9 那么它的最多节点应该是 511 所以说这一题选B 题目二 …

AI算力需求激增:全球服务器市场迎来黄金发展期

AI算力需求的暴增正在推动全球服务器规模的快速增长。这一趋势主要源于人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;特别是大模型算法的应用&#xff0c;使得智能算力需求激增。 麦肯锡预测&#xff0c;在AI大模型相关算力需求的快速增加推动下&#xff0c;以…

指挥中心操作台的形状及空间布局

在现代化的指挥中心&#xff0c;操作台的形状设计至关重要&#xff0c;它不仅影响着操作人员的工作效率和舒适度&#xff0c;还关系到整个指挥系统的运行效果。常见的指挥中心操作台形状多种多样&#xff0c;以满足不同的功能需求和空间布局。 直线型操作台 直线型操作台是最为…

AI芯片-系统架构师(二十二)

1、&#xff08;重点&#xff09;&#xff08;&#xff09;中&#xff0c;编程开发人员分为首席程序员和“类”程序员。 A自适应软件开发&#xff08;ASD&#xff09; B极限编程&#xff08;XP&#xff09;开发方法 C开放统一过程开发方法&#xff08;Open UP&#xff09; …

如何在Java中实现Excel操作

如何在Java中实现Excel操作 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨如何在Java中实现对Excel文件的操作&#xff0c;这在日常的数据处…

如何使用echart画k线图

使用ECharts绘制K线图需要以下步骤&#xff1a; 1. 引入ECharts库 首先&#xff0c;在HTML文件中引入ECharts库的文件。可以从ECharts官方网站上下载最新版本的库文件&#xff0c;并将其引入到HTML文件中。例如&#xff1a; html <script src"echarts.min.js">…

基于golang的文章信息抓取

基于golang的文章信息抓取 学习golang爬虫&#xff0c;实现广度爬取&#xff0c;抓取特定的网页地址&#xff1a;测试站点新笔趣阁&#xff08;https://www.xsbiquge.com/&#xff09; 主要学习golang的goroutine和channel之间的协作&#xff0c;无限爬取站点小说的地址仅限书目…

C语言 | Leetcode C语言题解之第212题单词搜索II

题目&#xff1a; 题解&#xff1a; class Solution { public:struct Node{int id;Node* son[26];Node(){id -1;for(int i 0; i < 26; i) son[i] NULL;}}* root;vector<vector<char>> g;unordered_set<int> ids;vector<string> res;int dx[4] …

Windows编程原理-消息驱动的机制

Windows为每一个输入事件产生一个输入消息&#xff0c;如&#xff1a; 移动鼠标按键…… 从程序角度看待Windows消息处理 Windows使用一个窗口前必须&#xff1a; 填充一个结构&#xff1a;WNDCLASS注册窗口创建窗口使用窗口撤销窗口 从这个机制看&#xff0c;windows操作系统…

前端面试题1

解释一下什么是闭包&#xff08;Closure&#xff09;&#xff0c;并给出一个实际应用场景。 解答: 闭包是指有权访问另一个函数作用域中的变量的函数&#xff0c;创建闭包最常见的方式就是在一个函数内部创建另一个函数。闭包可以让内部函数访问到外部函数的作用域&#xff0c;…