Vue封装文件上传组件(支持图片、PDF、Excel、word预览下载)

news2024/9/21 11:49:07

一、准备工作

安装预览依赖包:exceljs、mammoth、vue-pdf

二、封装组件

文件上传组件

fileUploadPro.vue。默认预览、下载是true,可通过isPreView、isDownLoad控制

<template>
    <div style="display: flex">
        <el-upload
                multiple
                action=""
                ref="uploadF"
                :show-file-list="false"
                :file-list="fileList"
                :http-request="fileUpLoad"
        >
            <el-button v-if="!readOnly" size="mini" type="primary">点击上传</el-button>
        </el-upload>
        <div style="flex-grow: 1;flex-wrap: wrap">
            <el-tag
                    @close="removeFile(index)"
                    v-for="(tag, index) in fileList"
                    :key="tag.fileId"
                    :closable="true"
                    type="info">
                    <div style="float: left">
                        {{tag.name}}
                    </div>
                    <div v-if="isPreView" class="iconStyle" @click="preView(tag)">
                        <i  class="el-icon-view"></i>
                    </div>
                    <div v-if="isDownLoad" class="iconStyle" @click="downLoad(tag)">
                        <i  class="el-icon-download"></i>
                    </div>
            </el-tag>
        </div>
    </div>
</template>
<script>
    export default {
        name: "fileUploadPro",
        props: {
            fileList: {
                type: Array,
                default: []
            },
            isPreView: {
                type: Boolean,
                default: true
            },
            isDownLoad: {
                type: Boolean,
                default: true
            },
            readOnly:{
                type: Boolean,
                default: false
            }
        },
        data() {
            return {

            }
        },
        methods:{
            fileUpLoad(e) {
                let file = e.file
                let formData = new FormData();
                formData.append("file", file); // 'file' 可变 相当于 input 表单的name 属性
                formData.append("name", file.name);
                formData.append("type", file.type);
                formData.append("size", file.size);
                formData.append("lastModifiedDate", file.lastModifiedDate);
                this.$http({
                    method: 'post',
                    url: "/base/ctBaseFile/saveFile50",
                    data: formData
                }).then((response) => {
                    if (response.data.code === 200) {
                        this.$message.success('上传成功')
                        this.fileList.push({
                            fileId: response.data.data.ctBaseFile.id,
                            name: file.name
                        })
                    }
                })
            },
            removeFile(index) {
                this.fileList.splice(index, 1)
            },
            preView(file) {
                let fileUrl = '';
                let fileType = '';
                if (file) {
                    fileUrl = this.$fileUrl + '/common/getFileRes/' + file.fileId
                    const addTypeArray = file.name.split(".");
                    const addType = addTypeArray[addTypeArray.length - 1];
                    if (addType === "pdf") {
                        fileType = 'pdf'
                    }else if(addType === 'xls' || addType === 'xlsx'){
                        fileType = 'excel'
                    }else if (addType === "doc" || addType === "docx") {
                        fileType = 'word'
                    } else if (["png", "jpg", "jpeg"].includes(addType)) {
                        fileType = 'image'
                    } else {
                        fileType = addType
                    }
                }
                this.$emit("preView",fileType,fileUrl);
                //that.showModal = true
            },
            downLoad(file){
                let a = document.createElement("a");//创建a标签
                a.setAttribute("href", this.$fileUrl + '/common/getFileRes/' + file.fileId);//设置文件下载地址
                a.setAttribute('target', '_blank');//在当前页面创建下载
                document.body.appendChild(a);//添加到body
                a.click();//触发事件
                document.body.removeChild(a);//移除标签
            },
        }
    }
</script>
<style scope>
    .iconStyle{
        float: left;
        width: 16px;
        height: 16px;
        line-height: 16px;
        text-align: center;
        position: relative;
        top:7px;
        margin-left: 6px;
        border-radius: 50%;
        cursor: pointer;
    }
    .iconStyle:hover{
        background-color: #909399;
        color: #fff;
    }
</style>

预览组件

preViewDialog.vue

<template>
    <div>
        <!-- Modal -->
        <el-dialog
                :title="'预览' + fileType"
                :visible.sync="showModal"
                width="70%"
                top="5vh"
                :before-close="handleClose"
                :close-on-click-modal="false"
        >
            <!-- Conditional rendering based on fileType -->
            <div v-if="fileType === 'image'" style="text-align:center">
                <img v-loading="loading" style="height: 400px" :src="fileUrl" alt="预览图片">
            </div>
            <div v-else-if="fileType === 'excel'">
                <el-table v-loading="loading" size="mini" :data="excelData" height="400" width="100%" :show-header="false">
                        <el-table-column width="150" v-for="(cell, key) in excelData[0]" :key="key" :prop="key" :label="key">
                        </el-table-column>
                </el-table>
            </div>
            <div v-else-if="fileType === 'pdf'">
                <!-- Render PDF preview here -->
                <VuePdf v-loading="loading" :src="pdfUrl"></VuePdf>
            </div>
            <div v-else-if="fileType === 'word'">
                <!-- Render Word preview here -->
                <div v-loading="loading" v-html="wordContent"></div>
            </div>
            <div v-else>
                <p>不支持的文件类型或未提供URL。</p>
            </div>

            <!-- Close Button -->
            <span slot="footer" class="dialog-footer">
                <el-button type="primary" @click="downLoad(fileUrl)">下 载</el-button>
                <el-button type="info" @click="closeModal">关 闭</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
    import ExcelJS from 'exceljs';
    import mammoth from 'mammoth';
    import VuePdf from 'vue-pdf';

    export default {
        props: {
            fileType: {
                type: String,
                required: true,
            },
            fileUrl: {
                type: String,
                required: true
            }
        },
        components: {
            VuePdf,
        },
        data() {
            return {
                pdfUrl:'',
                loading: true,
                excelContent: '',
                wordContent: '',
                showModal: false,
                excelData: [],
            };
        },
        mounted() {
            this.showModal = true
            this.loadFile();
        },
        methods: {
            async loadFile() {
                switch (this.fileType) {
                    case 'excel':
                        await this.loadExcel();
                        break;
                    case 'word':
                        await this.loadWord();
                        break;
                    case 'pdf':
                        // 加载 PDF 的逻辑
                        await this.loadPdf();
                        break;
                    default:
                        this.loading = false;
                        break;
                }
            },
            closeModal() {
                this.loading = true;
                this.$emit('close-modal');
            },
            async loadExcel() {
                try {
                    const response = await fetch(this.fileUrl);
                    if (!response.ok) {
                        throw new Error(`HTTP error! Status: ${response.status}`);
                    }
                    const arrayBuffer = await response.arrayBuffer();
                    const workbook = new ExcelJS.Workbook();
                    await workbook.xlsx.load(arrayBuffer);
                    const worksheet = workbook.worksheets[0]; // Assuming you want the first worksheet
                    if (worksheet) {
                        let data = [];
                        worksheet.eachRow((row, rowIndex) => {
                            let rowData = {};
                            row.eachCell((cell, colIndex) => {
                                rowData[`col${colIndex}`] = cell.value;
                            });
                            data.push(rowData);
                        });
                        this.excelData = data;
                    } else {
                        this.excelData = [];
                    }
                } catch (error) {
                    console.error('Error loading Excel:', error);
                    this.excelData = [];
                } finally {
                    this.loading = false;
                }
            },
            async loadWord() {
                try {
                    const response = await fetch(this.fileUrl);
                    const arrayBuffer = await response.arrayBuffer();
                    const result = await mammoth.extractRawText({ arrayBuffer });
                    this.wordContent = result.value;
                } catch (error) {
                    this.wordContent = '加载Word文件失败。';
                } finally {
                    this.loading = false;
                }
            },
            async loadPdf() {
                try {
                    this.pdfUrl = VuePdf.createLoadingTask({
                        url:this.fileUrl,
                        cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.6.347/cmaps/',
                        cMapPacked: true
                    })
                    const response = await fetch(this.pdfUrl);
                    if (!response.ok) {
                        throw new Error(`HTTP error! Status: ${response.status}`);
                    }
                } catch (error) {
                    console.error('Error fetching data:', error);
                }finally {
                    this.loading = false
                }
            },
            handleClose() {
                this.closeModal()
            },
            downLoad(file){
                let a = document.createElement("a");//创建a标签
                a.setAttribute("href", file);//设置文件下载地址
                a.setAttribute('target', '_blank');//在当前页面创建下载
                document.body.appendChild(a);//添加到body
                a.click();//触发事件
                document.body.removeChild(a);//移除标签
            },
        },
    };
</script>

<style scoped>
</style>

三、组件调用

<template>
    <div>
        <fileUploadPro
                :file-list.sync="fileList"
                :isPreView="true"
                :isDownLoad="false"
                @preView="preView"/>
        
        <previewDialog
                v-if="showModal"
                :file-type="fileType"
                :file-url="fileUrl"
                @close-modal="showModal = false"/>
    </div>
</template>
<script>
    import previewDialog from '../components/previewDialog';
    import fileUploadPro from "../components/fileUploadPro";
    export default {
        name: "parentXXX",
        components:{previewDialog,fileUploadPro},
        data() {
            return{
              fileList:[],
              fileType: '',
              fileUrl:'',
              showModal: false,
            }
        },
        methods:{
            preView(type,url){
                this.fileUrl = url;
                this.fileType = type;
                this.showModal = true
            },

        }
    }
</script>

四、效果

 

 

 

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

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

相关文章

BUUCTF逆向wp [MRCTF2020]Transform

第一步 查壳。该题为64位。 第二步 进入主函数&#xff0c;跟进dword_40F040,它应该与关键字符串有关 分析一下&#xff1a; 初始化和输入 sub_402230(argc, argv, envp); 这行可能是一个初始化函数&#xff0c;用于设置程序环境或处理命令行参数。具体功能不明&#xff0c…

不同业务场景下通过mars3d实现绕点旋转效果

1.鼠标单击地图某一处就对该点进行绕点旋转效果 相关代码&#xff1a; 1.相关绕点旋转的初始化代码&#xff1a; const rotatePoint new mars3d.thing.RotatePoint({direction: false, // 方向 true逆时针&#xff0c;false顺时针time: 50 // 给定飞行一周所需时间(单位 秒)&…

神经网络中如何优化模型和超参数调优(案例为tensor的预测)

总结&#xff1a; 初级&#xff1a;简单修改一下超参数&#xff0c;效果一般般但是够用&#xff0c;有时候甚至直接不够用 中级&#xff1a;optuna得出最好的超参数之后&#xff0c;再多一些epoch让train和testloss整体下降&#xff0c;然后结果就很不错。 高级&#xff1a;…

使用Docker 实现 MySQL 循环复制(三)

系列文章 使用Docker 实现 MySQL 循环复制&#xff08;一&#xff09; 使用Docker 实现 MySQL 循环复制&#xff08;二&#xff09; 目录 系列文章1. 在主机上安装MySQL客户端2. 配置循环复制拓扑2.1 进入容器2.2 创建复制用户并授予复制权限2.3 复位二进制日志2.4 配置环形复…

Jenkins-zookeeper-docker-xxljob-rancher

文章目录 Jenkins实战1 新建任务需要的配置pipeline Zookeeper基础 Docker基础实操windows11 docker mysql DockerhouseDockerhubxxl-Job基础实战 Rancher基础思考 实战1 Rancher的某个namespace的scale为0 Jenkins 实战 1 新建任务需要的配置pipeline 该代码是Jenkinsfile&…

【Docker】基于Docker-compose创建LNMP环境

目录 一.Docker-compose 概述 1.容器编排管理与传统的容器管理的区别 2.docker-compose 作用 3.docker-compose 本质 4.docker-compose 的三大概念 二.YML文件格式及编写注意事项 1.yml文件是什么 2.yml问价使用注意事项 3.yml文件的基本数据结构 三.Docker-compose …

5G以太网和5G前传业务的有效解决方案——25G可调DWDM光模块

信息技术的迅猛发展和数据传输需求的不断增加&#xff0c;光通信技术在现代网络中扮演着至关重要的角色。DWDM技术通过在一根光纤上使用多个不同波长的光信号同时传输&#xff0c;大幅提高了数据传输的容量。而可调光模块则能够在多种波长之间进行切换&#xff0c;实现灵活、高…

如何用EXCEL自动解方程/方程组?利用 矩阵乘法X=A-*B,X=mmult(minverse(A), B)

目录 问题的由来 1 数据 → 模拟分析 → 单变量求解 1.1 找一个单元格填入公式 1.2 功能入口 1.3 选择单变量求解&#xff0c;分别填入内容 1.4 求解 1.5 这个感觉用处不大 2 重点介绍&#xff0c;用EXCEL进行矩阵运算解方程的操作 2.1 运用EXCEL进行矩阵运算&…

ETL数据集成丨通过ETLCloud工具,将Oracle数据实时同步至Doris中

ETLCloud是一个全面的数据集成平台&#xff0c;专注于解决大数据量和高合规要求环境下的数据集成需求。采用先进的技术架构&#xff0c;如微服务和全Web可视化的集成设计&#xff0c;为用户提供了一站式的数据处理解决方案。 主要特点和功能包括&#xff1a; 实时数据处理&…

Android 使用FFmpeg解析RTSP流,ANativeWindow渲染 使用SurfaceView播放流程详解

文章目录 ANativeWindow 介绍ANativeWindow 的主要功能和特点ANativeWindow 的常用函数工作流程原理图通过ANativeWindow渲染RGB纯色示例 播放RTSP流工作流程图关键步骤解析自定义SurfaceView组件native 层解码渲染 效果展示注意事项 这篇文章涉及到jni层&#xff0c;以及Ffmpe…

pdf提取其中一页怎么操作?提取PDF其中一页的方法

pdf提取其中一页怎么操作&#xff1f;需要从一个PDF文件中提取特定页码的操作通常是在处理文档时常见的需求。这种操作允许用户选择性地获取所需的信息&#xff0c;而不必操作整个文档。通过选择性提取页面&#xff0c;你可以更高效地管理和利用PDF文件的内容&#xff0c;无论是…

负载均衡 lvs

1. 4层转发(L4) 与 7层转发(L7) 区别 4层转发(L4) 与 7层转发(L7) 区别 转发基于的信息 状态 常用的服务 L4 基于网络层和传输层信息&#xff1a; L4转发主要依赖于网络层IP头部(源地址&#xff0c;目标地址&#xff0c;源端口&#xff0c;目标端口)和传输层头部&#xff…

接口防刷!利用redisson快速实现自定义限流注解

问题&#xff1a; 在日常开发中&#xff0c;一些重要的对外接口&#xff0c;需要加上访问频率限制&#xff0c;以免造成资&#xfffd;&#xfffd;损失。 如登录接口&#xff0c;当用户使用手机号验证码登录时&#xff0c;一般我们会生成6位数的随机验证码&#xff0c;并将验…

【论文解读】VoxelNeXt: Fully Sparse VoxelNet for 3D Object Detection and Tracking

VoxelNeXt 摘要引言方法Sparse CNN Backbone AdaptationSparse Prediction Head 3D Tracking实验结论 摘要 3D物体检测器通常依赖于手工制作的方法&#xff0c;例如锚点或中心&#xff0c;并将经过充分学习的2D框架转换为3D。因此&#xff0c;稀疏体素特征需要通过密集预测头进…

电脑没有声音了怎么恢复?3个硬核操作,解救静音危机!

当你沉迷于电脑中的音乐、电影或是游戏时&#xff0c;突然一阵寂静袭来&#xff0c;是不是感觉就像突然按下了暂停键&#xff1f;这无疑是一场大灾难&#xff01;电脑没有声音了怎么恢复呢&#xff1f;急&#xff0c;今天小编带来了3个硬核操作&#xff0c;让你从无声的幽谷中爬…

二、BIO、NIO、直接内存与零拷贝

一、网络通信编程基础 1、Socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层&#xff0c;是一组接口&#xff0c;由操作系统提供&#xff1b; Socket将复杂的TCP/IP协议处理和通信缓存管理都隐藏在接口后面&#xff0c;对用户来说就是使用简单的接口进行网络应用编程…

【python】OpenCV—Scanner

文章目录 1、需求描述2、代码实现3、涉及到的库函数cv2.arcLengthcv2.approxPolyDPskimage.filters.threshold_localimutils.grab_contours 4、完整代码5、参考 1、需求描述 输入图片 扫描得到如下的结果 用OpenCV构建文档扫描仪只需三个简单步骤: 1.边缘检测 2.使用图像中…

02线性表 - 链表

这里是只讲干货不讲废话的炽念&#xff0c;这个系列的文章是为了我自己以后复习数据结构而写&#xff0c;所以可能会用一种我自己能够听懂的方式来描述&#xff0c;不会像书本上那么枯燥和无聊&#xff0c;且全系列的代码均是可运行的代码&#xff0c;关键地方会给出注释^_^ 全…

windows edge自带的pdf分割工具(功能)

WPS分割pdf得会员&#xff0c;要充值&#xff01;网上一顿乱找&#xff0c;发现最简单&#xff0c;最好用&#xff0c;免费的还是回到Windows。 Windows上直接在edge浏览器打开PDF&#xff0c;点击 打印 按钮,页面下选择对应页数 打印机 选择 另存为PDF&#xff0c;然后保存就…

memcached 高性能内存对象缓存

memcached 高性能内存对象缓存 memcache是一款开源的高性能分布式内存对象缓存系统&#xff0c;常用于做大型动态web服务器的中间件缓存。 mamcached做web服务的中间缓存示意图 当web服务器接收到请求需要处理动态页面元素时&#xff0c;通常要去数据库调用数据&#xff0c;但…