UniApp基于xe-upload实现文件上传组件
xe-upload地址:文件选择、文件上传组件(图片,视频,文件等) - DCloud 插件市场
致敬开发者!!!
感觉好用的话,给xe-upload的作者一个好评
背景:开发中经常会有上传附件的情况,但是找了一圈没有满意的组件,无意间看到xe-upload,满足我需要上传图片和视频的需求,直接使用示例项目开始二次开发my-file-upload。
修改内容:
1.文件的点击事件
2.对video类型文件的处理
3.根据文件名称创建file文件内容
<template><view><view class="upload-wrap"><view class="cu-form-group1"><view class="label">{{label}}:</view><view class="btn-click mgb-16 upload-btn" @click="handleUploadClick" v-show="!disabled"><image :src="icons.upload" mode="aspectFill" class="upload-icon" /><text class="upload-text">上传{{ label }}</text></view></view><view class="mgb-16 file-wrap" v-for="(item, index) in fileList" :key="index"><view class="btn-click file-line" @click="handlePreview(item)"><!-- <view class="btn-click file-line" @click="handleUploadFile(item)"> --><view class="file-info"><image :src="icons[item.fileType || 'file']" mode="aspectFill" class="file-icon" /><text class="file-name">{{ item.name || title[type] }}</text></view><image :src="icons.close" mode="aspectFill" class="file-icon"@click.stop="handleDeleteFile(index)" /></view></view><view class="mgb-16 file-wrap" v-if="fileList.length === 0 && disabled"><view class="file-line"><text class="file-empty">暂无数据</text></view></view><view><video id="myVideo" :src="videoUrl" autoplay loop muted objectFit="cover" v-if="showVideo"></video></view></view><xe-upload ref="XeUpload" :options="uploadOptions" @callback="handleUploadCallback"></xe-upload></view>
</template><script>export default {name: 'MyFileUpload',components: {},props: {type: {default: 'image', // image, video, filetype: String,},list: {default: () => ([]),type: Array,},// disabled: {// default: false,// type: Boolean,// },value: {type: String, // 或者是 File[],取决于你的需求default: null},maxFile: {type: Number, //最大上传数量default: 1},label: {type: String, // 或者是 File[],取决于你的需求default: '附件'},},data() {return {// uploadOptions 参数跟uni.uploadFile的参数是一样的(除了类型为Function的属性)uploadOptions: {// url: 'http://192.168.31.185:3000/api/upload', // 不传入上传地址则返回本地链接},uploadUrl: "/sys/common/upload",staticUrl: "/sys/common/static/",fileList: [],title: {image: '图片',video: '视频',file: '文件',},icons: {upload: '/static/xeUpload/icon_upload.png',close: '/static/xeUpload/icon_close.png',image: '/static/xeUpload/icon_image.png',video: '/static/xeUpload/icon_video.png',file: '/static/xeUpload/icon_file.png',},disabled: false,showVideo: false,videoUrl: ''};},watch: {value: {async handler(val) {if (val && val !== null && val !== undefined) {const url = this.$config.apiUrl + this.staticUrl + val;const file = this.urlToFile(url);this.fileList = [file];if (this.fileList.length === this.maxFile) {this.disabled = true;}}},immediate: true,deep: true,},},onLoad: function() {this.videoContext = uni.createVideoContext('myVideo', this)},methods: {handleUploadClick() {// 使用默认配置则不需要传入第二个参数// App、H5 文件拓展名过滤 { extension: ['.doc', '.docx'] } 或者 { extension: '.doc, .docx' }this.$refs.XeUpload.upload(this.type);// 可以根据当前的平台,传入选择文件的参数,例如// 注意 当chooseMedia可用时,会优先使用chooseMedia// // uni.chooseImage// this.$refs.XeUpload.upload(type, {// count: 6,// sizeType: ['original', 'compressed'],// sourceType: ['album'],// });// // uni.chooseVideo// this.$refs.XeUpload.upload(type, {// sourceType: ['camera', 'album'],// });// // uni.chooseMedia (微信小程序2.10.0+;抖音小程序、飞书小程序;京东小程序支持)// this.$refs.XeUpload.upload(type, {// count: 9,// sourceType: ['album', 'camera'],// });},handleUploadCallback(e) {console.log('UploadCallback', e);if (['choose', 'success'].includes(e.type)) {// 根据接口返回修改对应的response相关的逻辑const tmpFiles = (e.data || []).map(({response,tempFilePath,name,fileType}) => {// 当前测试服务返回的数据结构如下// {// "result": {// "fileName": "fileName",// "filePath": `http://192.168.1.121:3000/static/xxxxx.png`,// },// "success": true,// }const res = response?.result || {};const tmpUrl = res.filePath ?? tempFilePath;const tmpName = res.fileName ?? name;return {...res,url: tmpUrl,name: tmpName,fileType,};});this.fileList.push(...tmpFiles);this.handleUploadFile(e.data[0].tempFilePath);}},// 自定义上传handleUploadFile(url) {var that = this;console.log('UploadFile', url);if (url != undefined) {that.$http.upload(that.$config.apiUrl + that.uploadUrl + '?biz=temp', {filePath: url,name: 'file',}).then(res => {console.log('handleUpload success', res);//回传至表单that.$emit('input', res.data.message);const tmpData = JSON.parse(res.data);uni.showToast({title: tmpData.success ? '上传成功' : '上传失败',icon: 'none'});})}},// 预览handlePreview(item) {console.log('PreviewFile', item);const fileType = this.getFileType(item.name);const url = item.url;if (fileType === 'image') {return uni.previewImage({current: url,urls: [url],});}else if (fileType === 'video') {this.videoUrl = url;this.showVideo = !this.showVideo;//全屏显示// this.videoContext.requestFullScreen();}// #ifndef H5else if (fileType === 'office') {return uni.openDocument({filePath: url,fail: (err) => {console.log(err);uni.showToast({icon: 'none',title: '文件预览失败'});},});}// #endifelse{uni.showModal({title: '提示',content: url,showCancel: false,});}},handleDeleteFile(index) {this.fileList.splice(index, 1);if (this.fileList.length < this.maxFile) {this.disabled = false;}},urlToFile(url) {// 获取URL的最后一部分const lastPart = url.split('/').pop();// 获取文件名(不包括扩展名)const filenameWithoutExtension = lastPart.split('_').slice(0, -1).join('_');// 获取文件扩展名const extension = lastPart.split('.').pop();// 组合文件名和扩展名const filename = filenameWithoutExtension + '.' + extension;const fileType = this.getFileType(url);const file = {"fileName": filename,"fileKey": lastPart,"filePath": url,"url": url,"name": filename,"fileType": fileType}return file;},/*** 获取文件类型* @param {String} fileName 文件链接* @returns {String} fileType => '', image, video, audio, office, unknown*/getFileType(fileName = '') {const fileType = fileName.split('.').pop();// let suffix = flieArr[flieArr.length - 1];// if (!suffix) return '';// suffix = suffix.toLocaleLowerCase();const image = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp'];if (image.includes(fileType)) return 'image';const video = ['mp4', 'm4v'];if (video.includes(fileType)) return 'video';const audio = ['mp3', 'm4a', 'wav', 'aac'];if (audio.includes(fileType)) return 'audio';const office = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'plain'];if (office.includes(fileType)) return 'office';return 'unknown';},},};
</script><style lang="scss" scoped>view {box-sizing: border-box;}.label{text-align: justify;padding-right: 15px;white-space: nowrap;font-size: 15px;position: relative;height: 30px;line-height: 30px;}.cu-form-group1 {background-color: #ffffff;padding: 1px 15px 1px 0px;display: flex;align-items: center;min-height: 50px;// justify-content: space-between;}.btn-click {transition: all 0.3s;opacity: 1;}.btn-click:active {opacity: 0.5;}.mgb-16 {margin-bottom: 16rpx;&:last-child {margin-bottom: 0;}}.upload-wrap {width: 100%;border-radius: 16rpx;background: white;padding: 32rpx;.upload-btn {width: 60%;height: 120rpx;border: 2rpx dashed #AAAAAA;background: #FAFAFA;border-radius: 16rpx;display: flex;align-items: center;justify-content: center;flex-direction: column;.upload-icon {width: 48rpx;height: 48rpx;margin-bottom: 8rpx;}.upload-text {font-size: 26rpx;color: #9E9E9E;line-height: 40rpx;}}.file-wrap {.file-line {width: 100%;background: #F5F5F5;border-radius: 8rpx;padding: 16rpx;font-size: 26rpx;color: #1A1A1A;line-height: 40rpx;display: flex;align-items: center;justify-content: space-between;.file-info {width: 90%;display: flex;align-items: center;.file-name {max-width: 80%;padding-left: 16rpx;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}}.file-icon {width: 40rpx;height: 40rpx;flex-shrink: 0;}.file-empty {color: #999999;}}}}
</style>
父组件中引入使用
<my-file-upload type="file" v-model="model.attachment" label="附件"></my-file-upload>import myFileUpload from '@/components/my-componets/my-file-upload.vue';export default {name: "Test",components:{ myFileUpload },props:{formData:{type:Object,default:()=>{},required:false}},data(){return {model: {},}},onLoad: function (option) {}},created(){},methods:{}}
相关文章:

UniApp基于xe-upload实现文件上传组件
xe-upload地址:文件选择、文件上传组件(图片,视频,文件等) - DCloud 插件市场 致敬开发者!!! 感觉好用的话,给xe-upload的作者一个好评 背景:开发中经常会有…...

以太网交换安全:端口隔离
一、端口隔离 以太交换网络中为了实现报文之间的二层广播域的隔离,用户通常将不同的端口加人不同的 VLAN大型网络中,业务需求种类繁多,只通过 VLAN实现报文的二层隔离,会浪费有限的VLAN资源。而采用端口隔离功能,则可…...

望繁信科技CTO李进峰受邀在上海外国语大学开展流程挖掘专题讲座
2023年,望繁信科技联合创始人兼CTO李进峰博士受邀在上海外国语大学国际工商管理学院(以下简称“上外管院”)开展专题讲座,畅谈流程挖掘的发展及对企业数字化转型的价值。演讲吸引了上外教授和来自各行各业的领军企业学员百余人。 …...

nicegui组件button用法深度解读,源代码IDE运行和调试通过
传奇开心果微博文系列 前言一、button 组件基本用法1. 最基本用法示例2. 创建带图标按钮 二、button按钮组件样式定制1. 按钮的尺寸调整2. 改变颜色示例3. 按钮的自定义字体大小4. 圆角形状示例5. 自定义边框6. 添加阴影7. 复合按钮8. 浮动按钮9. 可扩展浮动操作按钮QFAB10. 按…...
数据结构:树(并查集)
并查集(Union-Find Disjoint Sets 或 Disjoint Set Union,简称DSU)是一种树型的数据结构,主要用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。在并查集中,通常将n个对象划分为不相交的…...

校园二手交易平台的小程序+ssm(lw+演示+源码+运行)
摘 要 随着社会的发展,社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景,运用软件工程原理和开发方法,它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…...
代码随想录训练营第46天|回文子序列
647. 回文子串 class Solution { public:int count0;void check(string& s, int left, int right){while(left>0&&right<s.length()&&s[left]s[right]){count;left--;right;}}int countSubstrings(string s) {for(int i0; i<s.length(); i){chec…...

使用 PowerShell 命令更改 RDP 远程桌面端口(无需修改防火墙设置)
节选自原文:Windows远程桌面一站式指南 | BOBO Blog 原文目录 什么是RDP开启远程桌面 检查系统版本启用远程桌面连接Windows 在Windows电脑上在MAC电脑上在Android或iOS移动设备上主机名连接 自定义电脑名通过主机名远程桌面使用Hosts文件自定义远程主…...
bilibili实现批量发送弹幕功能
代码如下: import random import time import requests from tkinter import *# 弹幕内容列表 # lis_text [ # 京口瓜洲一水间,钟山只隔数重山。,君不见黄河之水天上来,奔流到海不复回。,起舞弄清影,何似在人间! # ] lis_te…...

如何查看上网记录及上网时间?5种按步操作的方法分享!【小白也能学会!】
“知己知彼,百战不殆”,在数字时代,了解自己的上网行为和时长,不仅能帮助我们更好地管理时间,还能提升工作效率和生活质量。 今天,我们就来分享五种简单易懂的方法,即便是网络小白也能轻松学会…...

Nisshinbo日清纺pvs1114太阳模拟器手测
Nisshinbo日清纺pvs1114太阳模拟器手测...
多线程复杂系统调试利器——assert()
调试复杂系统时,最大的难点在于定位问题,如果弄清楚了问题产生的机理,那么就能有针对性的进行解决。 调试复杂系统时,遇到不好定位的问题,就要大胆去猜、去怀疑、去假设,尤其是应该重点怀疑多线程访问&…...
【2024.9.28练习】青蛙的约会
题目描述 题目分析 由于两只青蛙都在跳跃导致变量多,不妨采用物理题中的相对运动思想,设青蛙A不动,青蛙B每次跳米,两只青蛙的距离为米。正常来说,只要模拟青蛙B与青蛙A的相对运动过程,最终当青蛙B与青蛙A距…...

Python入门:类的异步资源管理与回收( __del__ 方法中如何调用异步函数)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 使用上下文管理器📝 使用 `__del__` 方法📝 结合使用上下文管理器与 `__del__`📝 资源回收的重要性⚓️ 相关链接 ⚓️📖 介绍 📖 在编程中,资源的管理和回收至关重要,尤其是在处理网络请求时。频…...

Android开发中的ViewModel
在Android应用开发中,ViewModel作为架构组件之一,扮演着管理UI数据和生命周期的关键角色。本文将深入探讨ViewModel如何感知View的生命周期,并分析其内核原理,帮助开发者更好地利用ViewModel优化应用架构。 一、ViewModel简介 在…...

Vue 3 文件编译流程详解与 Babel 的使用
文章目录 一、背景二、结论三、vitejs/plugin-vue 插件调试前物料准备vuePlugin 入口buildStart 方法transform 方法 四、vue/compiler-sfc 核心包parse 方法compileScript、rewriteDefault 方法compileTemplate 方法 五、整体架构六、总结参考资料 一、背景 最近正在研究 rea…...
Android常用C++特性之std::chrono
声明:本文内容生成自ChatGPT,目的是为方便大家了解学习作为引用到作者的其他文章中。 std::chrono 是 C11 引入的标准库中的时间处理工具,提供了以多种精度进行时间测量、处理和操作的功能。它允许开发者处理时间点(time_point&am…...
[Oracle] ORA-04036: 实例使用的 PGA 内存超出 PGA_AGGREGATE_LIMIT
有说该问题是因为触发了Oracle的BUG导致,最直接的解决方法就是重启数据库实例; Linux下数据库实例重启...

一次 Spring 扫描 @Component 注解修饰的类坑
问题现象 之前遇到过一个问题,在一个微服务的目录下有相同功能 jar 包的两个不同的版本,其中一个版本里面的类有 Component 注解,另外一个版本的类里面没有 Component 注解,且按照加载的顺序,没有 Component 注解的 j…...

深度学习:调整学习率
目录 前言 一、什么是调整学习率? 二、调整学习率的作用 三、怎么调整学习率 1.有序调整 2.自适应调整 3.自定义调整 4.调整示例 前言 在深度学习中,调整学习率是非常重要的,它对模型的训练效果和收敛速度有显著影响。 一、什么是调整…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...

02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术点解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术点解析 第一轮:基础概念问题 请解释Spring框架的核心容器是什么?它的作用是什么? 程序员JY回答:Spring框架的核心容器是IoC容器(控制反转…...