前端文件上传组件最全封装+删除+下载+预览

前言:使用的是若依的框架+element ui+vue2封装的。如果有不对的地方欢迎指出。后台管理使用,文件需要上传。回显列表,详情也需要回显+预览

// 开始封装组件:封装在 src/components/FileUpload/index.vue中
<template><div class="upload-file"><el-uploadmultiplename="multipartFile":action="uploadFileUrl":data="{ 上传时附带的额外参数 }":limit="limit":file-list="fileList":before-upload="handleBeforeUpload":on-exceed="handleExceed":on-error="handleUploadError":on-success="handleUploadSuccess":show-file-list="false":headers="headers"class="upload-file-uploader"ref="fileUpload"><!-- 上传按钮 --><el-button size="mini" type="primary" plain v-if="!disabled">选取文件</el-button><!-- 上传提示 --><div class="el-upload__tip" slot="tip" v-if="showTip && !disabled">请上传<template v-if="fileSize">大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b></template><template v-if="fileType">格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b></template>的文件</div></el-upload><!-- 文件列表,我们功能需要 删除文件、下载文件、预览文件功能 --><transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul" style="min-width: 300px"><li class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList" :key="file.fileId"><el-link class="link" :href="`${baseUrl}${file.filePath}`" :underline="false" target="_blank"><span class="el-icon-document" style="padidng-left: 10px">{{ getFileName(file.fileName) }}</span></el-link><div class="controls"><div class="ele-upload-list__item-content-action" style="width: 50px; text-align: center"><el-link :underline="false" @click="handleDelete(index)" type="danger" v-if="!disabled">删除</el-link></div><div class="ele-upload-list__item-content-action" style="width: 50px; text-align: center"><el-link :underline="false" @click="handlePreview(file)" type="danger">预览</el-link></div><div class="ele-upload-list__item-content-action" style="width: 50px; text-align: center"><el-link :underline="false" @click="handleDownload(file)" type="danger">下载</el-link></div></div></li></transition-group><!-- 文件预览功能,点击文件列表后的预览按钮,需要预览文档,pdf,excel,照片,视频,音频。其他没有封装,所以就不支持 --><el-dialog title="文件预览" :visible.sync="preview.open" append-to-body :before-close="previewCancel"><vue-office-docx v-if="fileSuffix == 'docx'" :src="preview.url" style="height: 100vh" /><vue-office-excel v-else-if="fileSuffix == 'xlsx'" :src="preview.url" style="width: auto; height: 100vh" /><vue-office-pdf v-else-if="fileSuffix == 'pdf'" :src="preview.url" style="height: 100vh" /><div style="text-align: center" v-else-if="fileSuffix == 'img'"><el-image style="width: 500px" :src="preview.url" fit="fill" :preview-src-list="[preview.url]"></el-image></div><div style="text-align: center" v-else-if="fileSuffix == 'mp3'"><audio controls loop ref="myAudio" autoplay class="my-audio"><source :src="preview.url" /></audio></div><div style="text-align: center" v-else-if="fileSuffix == 'mp4'"><video-app :src="preview.url" :second="1"></video-app></div><div style="text-align: center" v-else>暂不支持该文件预览,请下载预览</div></el-dialog></div>
</template><script>
import { getToken } from "@/utils/auth";
import { 查看和下载的接口,后端给的 } from "";//引入VueOfficeDocx组件,需要npm安装
import VueOfficeDocx from "@vue-office/docx";
import "@vue-office/docx/lib/index.css";//引入VueOfficeExcel组件,需要npm安装
import VueOfficeExcel from "@vue-office/excel";
import "@vue-office/excel/lib/index.css";//引入VueOfficePdf组件,需要npm安装
import VueOfficePdf from "@vue-office/pdf";import VideoApp from "./video.vue"; // 这个是我封装的视频预览的组件export default {name: "FileUpload",props: {// 数量限制limit: {type: Number,default: 5,},// 大小限制(MB)fileSize: {type: Number,default: 20,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ["docx", "pptx", "pdf"],},// 是否显示提示isShowTip: {type: Boolean,default: true,},formFileList: {type: Array,default: () => [],},disabled: {type: Boolean,default: false,},// 培训记录附件的类型busiType: {type: String,},},components: {VueOfficeDocx,VueOfficeExcel,VueOfficePdf,VideoApp,},data() {return {number: 0,uploadList: [],baseUrl: // 地址 ,uploadFileUrl: , // 上传文件服务器地址headers: {Authorization: "Bearer " + getToken(),},fileList: [],lookFile: false,url: "",// 文件预览preview: {open: false,url: "",},fileSuffix: "",};},watch: {// 编辑和详情的回显fileListformFileList: {handler(val) {if (val !== undefined) {this.fileList = val;}if (val == null) {this.fileList = [];return;}},deep: true,immediate: true,},},computed: {// 是否显示提示showTip() {return this.isShowTip && (this.fileType || this.fileSize);},},methods: {// 上传前校检格式和大小handleBeforeUpload(file) {// 校检文件类型if (this.fileType) {const fileName = file.name.split(".");const fileExt = fileName[fileName.length - 1];const isTypeOk = this.fileType.length ? this.fileType.indexOf(fileExt) >= 0 : [];if (!isTypeOk) {this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);return false;}}// 校检文件大小if (this.fileSize) {const isLt = file.size / 1024 / 1024 < this.fileSize;if (!isLt) {this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);return false;}}this.$modal.loading("正在上传文件,请稍候...");this.number++;return true;},// 文件个数超出handleExceed() {this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);},// 上传失败handleUploadError(err) {this.number--;this.$modal.msgError("上传文件失败,请重试");this.$modal.closeLoading();},// 上传成功回调handleUploadSuccess(res, file) {if (res.code === 200) {this.uploadList.push(res.data);this.$modal.closeLoading();this.uploadedSuccessfully();} else {this.number--;this.$modal.closeLoading();this.$modal.msgError(res.msg);this.$refs.fileUpload.handleRemove(file);this.uploadedSuccessfully();}},// 删除文件handleDelete(index) {this.fileList.splice(index, 1);this.$emit("input", this.listToString(this.fileList));},// 上传结束处理uploadedSuccessfully() {if (this.number > 0 && this.uploadList.length === this.number) {this.fileList = this.fileList.concat(this.uploadList);this.uploadList = [];this.number = 0;this.$emit("input", this.listToString(this.fileList));this.$modal.closeLoading();this.$emit("fileUploadSuccess", this.fileList);}},// 获取文件名称getFileName(name) {if (name?.lastIndex/Of("/") > -1) {return name.slice(name.lastIndexOf("/") + 1);} else {return name;}},// 对象转成指定字符串分隔listToString(list, separator) {let strs = "";separator = separator || ",";for (let i in list) {strs += list[i].url + separator;}return strs != "" ? strs.substr(0, strs.length - 1) : "";},resetFileList() {this.fileList = [];},// 下载handleDownload(file) {downloadFile(file.fileId).then((res) => {this.exportFunction(res, file.fileName, file.fileType);});},exportFunction(response, name, type) {const link = document.createElement("a");const blob = new Blob([response], { type });link.style.display = "none";link.href = URL.createObjectURL(blob);link.setAttribute("download", name, type);document.body.appendChild(link);link.click();document.body.removeChild(link);},// 预览handlePreview(file) {this.preview.url = "";if (file.fileType.indexOf("image") !== -1) {this.fileSuffix = "img";} else {this.fileSuffix = file.suffix;}showFileURL(file.fileId).then((res) => {this.preview.url = defaultSettings.minioUrl + res;if (file.suffix == "mp3") {this.$nextTick((res) => {this.$refs.myAudio.load();this.$refs.myAudio.play();});}this.preview.open = true;});},previewCancel() {this.preview.open = false;this.preview.url = "";if (this.fileSuffix == "mp3") {this.$refs.myAudio.pause();}},},
};
</script><style scoped lang="scss">
::v-deep .el-button--primary.is-plain {color: var(--select-selected-color);background: var(--table-content-bColor);border-color: var(--search-back);
}
::v-deep .el-button--primary.is-plain:hover,
::v-deep .el-button--primary.is-plain:focus {border-color: var(--select-selected-color);background-color: var(--select-selected-color);color: #fff !important;
}.upload-file-uploader {margin-bottom: 5px;
}
.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;color: inherit;.link {flex: 1;display: block;margin-left: 2px;::v-deep .el-icon-document {width: 310px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}}.controls {display: flex;}
}
.ele-upload-list__item-content-action .el-link {margin-right: 10px;
}
::v-deep {.x-spreadsheet-table {width: auto !important;}
}
.my-audio {width: 100%;
}
</style>

video组件封装:


<template><div class="m-video" :class="{'u-video-hover': !hidden}" :style="`width: ${width}px; height: ${height}px;`"><videoref="veo":style="`object-fit: ${zoom};`":src="src":poster="veoPoster":width="width":height="height":autoplay="autoplay":controls="!originPlay&&controls":loop="loop":muted="autoplay || muted":preload="preload"crossorigin="anonymous"@loadeddata="poster ? () => false : getPoster()"@pause="showPlay ? onPause() : () => false"@playing="showPlay ? onPlaying() : () => false"@click.prevent.once="onPlay"v-bind="$attrs">您的浏览器不支持video标签。</video><svg v-show="originPlay || showPlay" class="u-play" :class="{'hidden': hidden}" :style="`width: ${playWidth}px; height: ${playWidth}px;`" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4.75 6.75C4.75 5.64543 5.64543 4.75 6.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25 6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V6.75Z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 12L9.75 8.75V15.25L15.25 12Z"></path></svg></div>
</template>
<script>
export default {name: 'Video',props: {src: { // 视频文件url,必传,支持网络地址 https 和相对地址 require('@/assets/files/Bao.mp4')type: String,required: true,default: ''},poster: { // 视频封面url,支持网络地址 https 和相对地址 require('@/assets/images/Bao.jpg')type: String,default: ''},second: { // 在未设置封面时,自动截取视频第 second 秒对应帧作为视频封面type: Number,default: 0.5},width: { // 视频播放器宽度type: Number,default: 800},height: { // 视频播放器高度type: Number,default: 450},autoplay: { // 视频就绪后是否马上播放type: Boolean,default: false},controls: { // 是否向用户显示控件,比如进度条,全屏type: Boolean,default: true},loop: { // 视频播放完成后,是否循环播放type: Boolean,default: false},muted: { // 是否静音type: Boolean,default: false},preload: { // 是否在页面加载后载入视频,如果设置了autoplay属性,则preload将被忽略;type: String,default: 'auto' // auto:一旦页面加载,则开始加载视频; metadata:当页面加载后仅加载视频的元数据 none:页面加载后不应加载视频},showPlay: { // 播放暂停时是否显示播放器中间的暂停图标type: Boolean,default: true},playWidth: { // 中间播放暂停按钮的边长type: Number,default: 96},zoom: { // video的poster默认图片和视频内容缩放规则type: String,default: 'contain' // none:(默认)保存原有内容,不进行缩放; fill:不保持原有比例,内容拉伸填充整个内容容器; contain:保存原有比例,内容以包含方式缩放; cover:保存原有比例,内容以覆盖方式缩放}},data () {return {veoPoster: this.poster,originPlay: true,hidden: false}},mounted () {if (this.autoplay) {this.hidden = truethis.originPlay = false}/*自定义设置播放速度,经测试:在vue2中需设置:this.$refs.veo.playbackRate = 2在vue3中需设置:veo.value.defaultPlaybackRate = 2*/// this.$refs.veo.playbackRate = 2},methods: {/*loadeddata 事件在媒体当前播放位置的视频帧(通常是第一帧)加载完成后触发preload为none时不会触发*/getPoster () { // 在未设置封面时,自动获取视频0.5s对应帧作为视频封面// 由于不少视频第一帧为黑屏,故设置视频开始播放时间为0.5s,即取该时刻帧作为封面图this.$refs.veo.currentTime = this.second// 创建canvas元素const canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')// canvas画图canvas.width = this.$refs.veo.videoWidthcanvas.height = this.$refs.veo.videoHeightctx.drawImage(this.$refs.veo, 0, 0, canvas.width, canvas.height)// 把canvas转成base64编码格式this.veoPoster = canvas.toDataURL('image/png')},onPlay () {if (this.originPlay) {this.$refs.veo.currentTime = 0this.originPlay = false}if (this.autoplay) {this.$refs.veo.pause()} else {this.hidden = truethis.$refs.veo.play()}},onPause () {this.hidden = false},onPlaying () {this.hidden = true}}
}
</script>
<style lang="scss" scoped>
* {box-sizing: border-box;margin: 0;padding: 0;
}
.m-video {display: inline-block;position: relative;background: #000;cursor: pointer;.u-play {position: absolute;top: 0;right: 0;bottom: 0;left: 0;margin: auto;fill: none;color: #FFF;pointer-events: none;opacity: 0.7;transition: opacity .3s;path {stroke: #FFF;}}.hidden {opacity: 0;}
}
.u-video-hover {&:hover {.u-play {opacity: 0.9;}}
}
</style>

使用组件:

import FileUpload= from "@/components/FileUpload=";
<el-form-item label="文件上传"><file-uploadref="fileResetRef"@fileUploadSuccess="fileUploadSuccessHandle":formFileList="form.files" // 回显的数据文件列表:disabled="isReadonly" // 区分编辑还是查看:file-type="[ // 支持的类型'png','jpg','docx','xlsx','pptx','pdf','mp3','mp4','zip',]"></file-upload>
</el-form-item>
// 文件上传成功的展示
fileUploadSuccessHandle1(fileList) {this.form.files = fileList;
},

上传组件效果图:
在这里插入图片描述
上传的文件列表:
在这里插入图片描述

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

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

相关文章

slf4j+logback源码加载流程解析

slf4j绑定logback源码解析 Logger log LoggerFactory.getLogger(LogbackDemo.class);如上述代码所示&#xff0c;在项目中通常会这样创建一个Logger对象去打印日志。 然后点进去&#xff0c;会走到LoggerFactory的getILoggerFactory()方法&#xff0c;如下代码所示。 public …

Maven介绍安装和配置详解

点击下载《Maven介绍安装和配置详解》 1. Maven介绍 Maven是一个自动化构建工具&#xff0c;主要用于Java项目的构建和管理。它使用一种基于项目对象模型&#xff08;POM&#xff09;的概念&#xff0c;使得开发者能够使用一种统一的方式来管理项目的构建、报告和文档。 以下…

大模型提效105篇必读论文和代码汇总,涵盖预训练、注意力、微调等7个方向

大型语言模型&#xff08;LLMs&#xff09;在NLP领域中具有显著的优势&#xff0c;它们在语言理解和生成方面表现出了强大的能力&#xff0c;甚至可以进行复杂的推理任务。这些能力能让大模型在许多领域都有广泛的应用前景&#xff0c;比如文本生成、对话系统、机器翻译、情感分…

论文阅读——EfficientViT(cvpr2023)

EfficientViT: Memory Efficient Vision Transformer with Cascaded Group Attention 1、 从三个角度探讨如何提高vision transformers的效率&#xff1a;内存访问、计算冗余和参数使用。 2.1. Memory Efficiency 红色字体表示操作所花费的时间主要由内存访问决定&#xff0c;…

C语言 linux文件操作(一)

文章目录 一、linux文件权限1.1文件描述符1.2文件描述符的范围和默认值1.3打开文件和文件描述符1.4标准文件描述符1.5文件描述符的重定向和关闭1.6I/O 操作1.7使用文件描述符进行进程通信1.8资源限制 二、C语言文件读写2.1open 函数2.2 flags参数详解2.3 lseek 函数 一、linux文…

Javaweb之数据库连接池以及lombok类库的详细解析

3. 数据库连接池 在前面我们所讲解的mybatis中&#xff0c;使用了数据库连接池技术&#xff0c;避免频繁的创建连接、销毁连接而带来的资源浪费。 下面我们就具体的了解下数据库连接池。 3.1 介绍 没有使用数据库连接池&#xff1a; 客户端执行SQL语句&#xff1a;要先创建一…

JS + CSS 实现高亮关键词(不侵入DOM)

之前在做关键词检索高亮功能的时候&#xff0c;研究了下目前前端实现高亮的几种方式&#xff0c;第一就是替换dom元素实现高亮&#xff0c;第二就是利用浏览器新特性Css.highlights结合js选区与光标与CSS高亮伪类实现&#xff0c;实现功能如下&#xff1a; 一、页面布局 一个…

叫板GPT-4的Gemini,我做了一个聊天网页,可图片输入,附教程

先看效果&#xff1a; 简介 Gemini 是谷歌研发的最新一代大语言模型&#xff0c;目前有三个版本&#xff0c;被称为中杯、大杯、超大杯&#xff0c;Gemini Ultra 号称可与GPT-4一较高低&#xff1a; Gemini Nano(预览访问) 为设备端体验而构建的最高效模型,支持离线使用场景。…

[Redis实战]分布式锁

四、分布式锁 4.1 基本原理和实现方式对比 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁&#xff0c;只要大家使用的是同一把锁&#xff0c;那么我们就能锁住线程&#xff0c;不让线程进行&#xf…

Rust赋值语句和数字类型

赋值语句 在Rust中&#xff0c;使用let关键字定义变量。格式是let 变量名:变量类型 变量值;&#xff0c;下边是个例子&#xff1a; let age:i32 18;这就是定义一个有符号32位的数字变量age&#xff0c;而其中的值是18。 而在C语言定义变量的语句格式是类型 变量名 变量值。…

【网络技术】【Kali Linux】Wireshark嗅探(三)用户数据报(UDP)协议

一、实验目的 本次实验使用wireshark流量分析工具进行网络嗅探&#xff0c;旨在了解UDP协议的报文格式。 二、网络环境设置 本次实验使用Kali Linux虚拟机完成&#xff0c;主机操作系统为Windows 11&#xff0c;虚拟化平台选择Oracle VM VirtualBox&#xff0c;组网模式选择…

electron使用webview出现空白页面解决办法

在使用webview标签的时候&#xff0c;出现了空白页面的情况&#xff0c;刚开始以为没有生效&#xff0c;后来发现页面上是有这个标签的&#xff0c;但是没有展示出内容&#xff0c;后来看了官网&#xff0c;默认情况下&#xff0c;webview标签在 Electron > 5 中被禁用。 &l…

pytorch机器学习各种激活函数总结(不完整学习更新中~)

pytorch各种激活函数总结 0.思维导图预览1. ReLU函数2. Sigmoid函数3. Softmax函数4. Tanh函数5.&#xff08;学习后更新&#xff09; 0.思维导图预览 1. ReLU函数 ReLU&#xff08;Rectified Linear Unit&#xff09;线性整流函数 其公式为&#xff1a; f ( x ) M a x ( 0 …

传感器原理与应用复习--具体场景的应用

文章目录 测量转速测量厚度测量加速度测量液体压强测量含水量测量温度测量流速 测量转速 磁电感应传感器 霍尔传感器 测量厚度 电涡流传感器 测量加速度 应变式传感器 差动变压器式传感器 测量液体压强 电感传感器 电容传感器 测量含水量 半导体传感器 微波传感器…

Prototype原型模式(对象创建)

原型模式&#xff1a;Prototype 链接&#xff1a;原型模式实例代码 注解 模式定义 使用原型实例指定创建对象的种类&#xff0c;然后通过拷贝这些原型来创建新的对象。 ——《设计模式》GoF 目的 在软件系统中&#xff0c;经常面临这“某些结构复杂的对象”的创建工作&am…

Redis的集群模式:主从 哨兵 分片集群

基于Redis集群解决单机Redis存在的问题&#xff0c;在之前学Redis一直都是单节点部署 单机或单节点Redis存在的四大问题&#xff1a; 数据丢失问题&#xff1a;Redis是内存存储&#xff0c;服务重启可能会丢失数据 > 利用Redis数据持久化的功能将数据写入磁盘并发能力问题…

基于YOLOv8的目标跟踪技术

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;介绍了YOLOv8自带的目标跟踪技术以及评价指标&#xff0c;并教会你如何在YOLOv8使用 1.YOLOv8自带两种跟踪方法 ultralytics/cfg/trackers/文件夹下 1.1 ByteTrack介绍 https://arxiv.org/pdf/2110.06864.pdf 摘…

Python爬虫---selenium基本使用(支持无界面浏览器PhantomJS和Chrome handless)

为什么使用selenium&#xff1f; 使用urllib.request.urlopen()模拟浏览器有时候获取不到数据,所以使用selenium (1) selenium是一个用于web应用程序测试的工具 (2) selenium 测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样 (3) 支持通过各种driver (FirfoxDri…

PAT 乙级 1057 数零壹

给定一串长度不超过 10 5 的字符串&#xff0c;本题要求你将其中所有英文字母的序号&#xff08;字母 a-z 对应序号 1-26&#xff0c;不分大小写&#xff09;相加&#xff0c;得到整数 N&#xff0c;然后再分析一下 N 的二进制表示中有多少 0、多少 1。例如给定字符串 PAT (Bas…

人大金仓数据库与mysql比较

简介 人大金仓数据库是基于 PostgreSQL 开发的。 SQL语言 语法 关键字 KES&#xff1a; MYSQL&#xff1a; 语句 *特性MYSQLKES字符串字面量单引号()或 双引号(")十六进制字面量0x5461626c65&#xff0c;X5461626c65/BIT字面量b1000001,0b1000001/Boolean字面量常…