Vue2+Element实现Excel文件上传下载预览【超详细图解】

news2025/2/27 22:25:18

目录

一、需求背景

二、落地实现 

1.文件上传

图片示例 

HTML代码 

业务代码

2.文件下载

图片示例

方式一:代码

方式二:代码

3.文件预览

图片示例

方式一:代码

方式二:代码


一、需求背景

在一个愉快的年后,需求经理提出需要完成对单个Excel文件的上传、下载、预览的功能,对于一个没写过下载和预览的后端来说,真的十分痛苦,经过不断百度+努力看别人的博客,最终实现如下图所示

二、落地实现 

1.文件上传

图片示例 

HTML代码 

<template>
    <el-upload v-model="form.upload" ref="upload" name="file" action="" drag :on-remove="handleRemove" :on-success="handleSuccess" multiple :limit="1" accept=".xls,.xlsx" :before-upload="beforeUpload" :http-request="handleRequest" :on-exceed="handleExceed">
      <i class="el-icon-upload" style="color: #409eff"></i>
      <div class="el-upload__tip"><span style="color: #333333;font-size: 13px">点击或将文件拖拽到这里上传</span>
      </div>
      <div class="el-upload__tip"><span style="color: #999999;font-size: 13px">仅支持单文件上传,文件上传行数最多1000,上传格式支持:.xls .xlsx</span>
      </div>
    </el-upload>
<template>

 参数解释

name="file":是传到后端时,它接收这个文件的参数名叫file,本人没有仔细研究,因为在调接口时,可个性化定制参数名,后续贴的代码会提到。

action="":这个Element官方文档写的是一个上传的固定链接,假的,用不了。通常在开发中,也是自定义上传逻辑,所以这里置空。

drag:启用拖拽上传,Element默认是false,直接写drag,不写:drag="true"就是true了。

show-file-list:显示已上传文件列表,就是上传框下面的那行文件名,Element默认是false

multiple:支持多选文件,通常与limit搭配使用。

:limit="1":多选文件数量,如只需要单个文件就设置1。

accept=".xls,.xlsx":接受上传的文件类型,我的需求是只要Excel的。

:on-remove="handleRemove":文件列表移除文件时的方法,就是文件列表右边那个小X触发时调用的。

:on-success="handleSuccess":文件上传成功时的方法,比如弹出一个上传成功提示。

:before-upload="beforeUpload":上传文件之前的方法,通常用于上传文件前对文件的校验。

:http-request="handleRequest":自定义上传方式的方法,比如远程调用。

:on-exceed="handleExceed":文件超出个数限制时的方法,比如弹出一个仅支持单个文件的提示。

class="el-upload__tip":这个是Element封装好的样式,我的需求是需要文字在上传框里显示,所以都用el-upload__tip,官方文档还有个框外的用el-upload__text。

业务代码

export default {
  name: "upload-dialog",
  data() {
    return {};
  },
  methods: {
    handleSuccess(response, file, fileList) {
      // 文件上传成功的回调
      this.$message.success("上传成功");
    },
    handleRemove(file, fileList) {
      console.log("删除", file, fileList);
      // 看需要是否调用删除接口
    },
    beforeUpload(file) {
      // 在这里进行个性化校验
      const maxSize = 100 * 1024 * 1024; // 100MB(以字节为单位)
      if (file.size > maxSize) {
        // 这里可以添加你的提示逻辑(比如 Element UI 的 Message 警告)
        this.$message.warning("文件大小不能超过 100 MB");
        return false; // 阻止上传
      }
      return true;
    },
    handleRequest(option) {
      // 自定义上传函数,用于并发上传
      const formData = new FormData();
      // 这个file就是后端的接收这个文件的参数名,如果为其他,则设成其他
      formData.append("file", option.file);
      // 如果还需要其他参数比如id,name,就在这里继续加
      // formData.append("id", xxx);
      // 发送请求,这个uploadApi是import进来的,自己写
      uploadApi(formData).then(res => {
        // 自定义上传方法的话,需要手动触发文件上传成功的钩子,不然文件状态会一直处于ready
        option.onSuccess(null, option.file);
      }).catch(error => {
        // 自定义上传方法的话,需要手动触发文件上传失败的钩子,不然文件状态会一直处于ready
        option.onError(error, option.file, null);
      });
    },
    // 文件超出个数限制时的钩子
    handleExceed(files, fileList) {
      this.$message.warning("仅支持单个文件上传");
    },
  },
};

2.文件下载

图片示例

我是通过<a></a>标签去实现文件下载的,如果想通过点击按钮实现,那么,在按钮里面套塞<a></a>即可

方式一:代码

<template>
    <a :href="fileUrl" download>>文件</a>
</template>
export default {
  data() {
    return {
      fileUlr: 'http://static.shanhuxueyuan.com/demo/excel.xlsx'
    };
  },
}

这个href放是一个像http://static.shanhuxueyuan.com/demo/excel.xlsx这样的cdn文件地址,点击就可以直接下载到本地。

如果需要通过二进制流、Blob对象实现的话,则自定义按钮,触发方法去调用。(详情请看方式二)

方式二:代码

<template>
  <el-button type="text" @click="downloadFile(fileName)">
    <span style="color: #0000FF">文件名</span>
  </el-button>
</template>
export default {
  data() {
    return {};
  },
  methods: {
    downloadFile(fileName) {
        // 生成随机数据(示例:5行3列)
        const data = [
          ["Name", "Age", "Join Date"], // 表头
          ...Array.from({length: 5}, (_, i) => [
            `User ${i + 1}`, // 姓名
            Math.floor(Math.random() * 30 + 20), // 随机年龄 (20-50)
            new Date().toISOString().split("T")[0], // 当前日期
          ]),
        ];

        // 创建工作表
        const worksheet = XLSX.utils.aoa_to_sheet(data);

        // 创建工作簿
        const workbook = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");

        // 生成 Excel 文件
        const excelBuffer = XLSX.write(workbook, {
          bookType: "xlsx",
          type: "array",
        });

        const blob = new Blob([excelBuffer], {
          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        });

        // 创建一个链接元素
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = fileName; // 设置下载的文件名
        // 触发下载
        link.click();
        // 释放 URL 对象
        URL.revokeObjectURL(link.href);

        this.$message.success("文件下载成功");
    },
  }
}

3.文件预览

图片示例

我的需求是:点击文件名,浏览器新打开一个标签页,展示文件内容。

这个需要在route中额外添加一个路由映射

{
        path: '/preview',
        name: 'preview',
        meta: { title: '文件预览', requiresAuth: false },
        component: () => import('@/views/preview.vue')
},

还需要额外结合@vue-office/excel写页面 

npm install @vue-office/excel vue-demi

方式一:代码

入口代码

<template>
    <el-button type="text">
        <a :href="'#/preview?fileUrl='+fileUrl" target="_blank">详情</a>
    </el-button>
</template>
export default {
  data() {
    return {
      fileUlr: 'http://static.shanhuxueyuan.com/demo/excel.xlsx'
    };
  },
}

 页面代码

<template>
  <vue-office-excel :src="excel" @rendered="rendered" @error="errorHandler"/>
</template>
<script>
//引入VueOfficeExcel组件
import VueOfficeExcel from "@vue-office/excel";
//引入相关样式
import "@vue-office/excel/lib/index.css";
//引入解析Excel文件组件
import XLSX from "xlsx";

export default {
  components: {
    VueOfficeExcel,
  },
  data() {
    return {
      // 设置文档地址,支持三种格式
      // string: Excel文件的网络地址,如cdn地址
      // ArrayBuffer:以ArrayBuffer格式读取Excel文件的内容
      // Blob:以Blob格式读取Excel文件的内容
      excel: "",
    };
  },
  mounted() {
    this.getExcel();
  },
  methods: {
    rendered() {
      console.log("渲染完成");
    },
    errorHandler() {
      console.log("渲染失败");
    },
    getExcel() {
      this.excel = this.$route.query.fileUrl;
    }
  },
};
</script>

这样直接就是浏览器新打开一个标签页展示文件内容。与文件下载十分相似。

如果需要使用二进制流、Blob对象打开的话。(详情请看方式二)

方式二:代码

入口代码

<template>
    <el-button type="text">
        <a :href="'#/preview'" target="_blank">详情</a>
    </el-button>
</template>

页面代码

<template>
  <vue-office-excel :src="excel" @rendered="rendered" @error="errorHandler"/>
</template>
<script>
//引入VueOfficeExcel组件
import VueOfficeExcel from "@vue-office/excel";
//引入相关样式
import "@vue-office/excel/lib/index.css";
//引入解析Excel文件组件
import XLSX from "xlsx";

export default {
  components: {
    VueOfficeExcel,
  },
  data() {
    return {
      // 设置文档地址,支持三种格式
      // string: Excel文件的网络地址,如cdn地址
      // ArrayBuffer:以ArrayBuffer格式读取Excel文件的内容
      // Blob:以Blob格式读取Excel文件的内容
      excel: "",
    };
  },
  mounted() {
    this.createRandomExcel();
  },
  methods: {
    rendered() {
      console.log("渲染完成");
    },
    errorHandler() {
      console.log("渲染失败");
    },
    // 创建随机 Excel 文件
    createRandomExcel() {
      // 生成随机数据(示例:5行3列)
      const data = [
        ["Name", "Age", "Join Date"], // 表头
        ...Array.from({length: 5}, (_, i) => [
          `User ${i + 1}`, // 姓名
          Math.floor(Math.random() * 30 + 20), // 随机年龄 (20-50)
          new Date().toISOString().split("T")[0], // 当前日期
        ]),
      ];

      // 创建工作表
      const worksheet = XLSX.utils.aoa_to_sheet(data);

      // 创建工作簿
      const workbook = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");

      // 生成 Excel 文件
      const excelBuffer = XLSX.write(workbook, {
        bookType: "xlsx",
        type: "array",
      });

      const blob = new Blob([excelBuffer], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      });

      this.excel = blob;
    },
  },
};
</script>

上述代码,也适用于展示Word和PPT文件,修改对应的格式即可。 

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

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

相关文章

[记录贴] 火绒奇怪的进程保护

最近一次更新火绒6.0到最新版&#xff0c;发现processhacker的结束进程功能无法杀掉火绒的进程&#xff0c;弹窗提示如下&#xff1a; 可能是打开进程时做了权限过滤&#xff0c;火绒注册了两个回调函数如下&#xff1a; 但奇怪的是&#xff0c;在另外一台机器上面更新到最新版…

【蓝桥杯】每天一题,理解逻辑(1/90)【Leetcode 移动零】

文章目录 题目解析讲解算法原理【双指针算法思路】(数组下标充当指针)如何划分和执行过程大致 代码详情 题目解析 题目链接&#xff1a;https://leetcode.cn/problems/move-zeroes/description/ 题目意思解析 把所有的零移动到数组的末尾保持非零元素的相对顺序 理解了这两层…

pycharm远程连接服务器运行pytorch

Linux部署pytorch 背景介绍 不同的开源代码可能需要不同的实验环境和版本&#xff0c;这时候的确体现出Anaconda管理环境的好处了&#xff0c;分别搞一个独立环境方便管理。 有的教程建议选择较旧的版本&#xff0c;但笔者建议在条件允许的情况下安装最新版&#xff0c;本次…

java练习(41)

ps&#xff1a;题目来自力扣 最接近的三数之和 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 import java.util.Arrays;class Solut…

PDF扫描档智能方向识别:多模型投票机制的实践测试 救活古典书籍

2025-02-22 20:10物联全栈123 尊敬的诸位&#xff01;我是一名物联网工程师。关注我&#xff0c;持续分享最新物联网与AI资讯和开发实战。期望与您携手探寻物联网与 AI 的无尽可能 RAG知识库搭建的过程中&#xff0c;扫描档pdf的支持和准确率一直是个大家都不愿主动提起的事情…

轻松搭建:使用Anaconda创建虚拟环境并在PyCharm中配置

一、使用Anaconda创建虚拟环境 1. 安装Anaconda 2..conda常用的命令 3. 创建虚拟环境-以搭建MachineVision为例 4. 激活虚拟环境 5. 安装依赖包 二、PyCharm配置环境 在进行Python项目开发时&#xff0c;合理的环境管理是必不可少的&#xff0c;特别是当你在多个项目中…

驱动开发系列39 - Linux Graphics 3D 绘制流程(二)- 设置渲染管线

一:概述 Intel 的 Iris 驱动是 Mesa 中的 Gallium 驱动,主要用于 Intel Gen8+ GPU(Broadwell 及更新架构)。它负责与 i915 内核 DRM 驱动交互,并通过 Vulkan(ANV)、OpenGL(Iris Gallium)、或 OpenCL(Clover)来提供 3D 加速。在 Iris 驱动中,GPU Pipeline 设置 涉及…

MinIO整合SpringBoot实现文件上传、下载

文章目录 配置1. 部署MinIO服务2. 整合SpringBoot 功能实现1. 文件上传2. 文件下载 总结 配置 1. 部署MinIO服务 这里以docker为例&#xff1a; 安装minio命令docker run -p 9000:9000 -p 9001:9001 \ --name minio \ -v /path/to/data:/data \ -e "MINIO_ROOT_USERmin…

FreeRTOS(3)列表List

在 FreeRTOS 的源码中大量地使用了列表和列表项&#xff0c;因此想要深入学习 FreeRTOS&#xff0c;列表和列表项是必备的基础知识。这里所说的列表和列表项&#xff0c;是 FreeRTOS 源码中 List 和 List Item 的 直译&#xff0c;事实上&#xff0c; FreeRTOS 中的列表和列表项…

C++和OpenGL实现3D游戏编程【连载23】——几何着色器和法线可视化

欢迎来到zhooyu的C++和OpenGL游戏专栏,专栏连载的所有精彩内容目录详见下边链接: 🔥C++和OpenGL实现3D游戏编程【总览】 1、本节实现的内容 上一节课,我们在Blend软件中导出经纬球模型时,遇到了经纬球法线导致我们在游戏中模型光照显示问题,我们在Blender软件中可以通过…

Harmony开发笔记(未完成)

一、感想 作为一名拥有11年经验的Android开发者&#xff0c;我亲历了Android从高速发展到如今面临“僧多粥少”的过程。技术的世界瞬息万变&#xff0c;没有一种技术能够让人依赖一辈子。去年初&#xff0c;我自学了鸿蒙系统&#xff0c;并顺利通过了鸿蒙官方的初级和高级认。…

【Java面试】创建线程有哪几种方式

目录 1.继承Thread类 2.实现Runnable接口 3.实现Callable接口和FutureTask 4.使用Executor框架&#xff08;线程池&#xff09; Java并发编程中不同接口和类之间的关系 总结 1.继承Thread类 优点&#xff1a; 简单直观。直接继承Thread类&#xff0c;可以方便地使用Threa…

在Linux环境下利用MTCNN进行人脸检测(基于ncnn架构)

概述 本文将详细介绍如何在Linux环境下部署MTCNN模型进行人脸检测&#xff0c;并使用NCNN框架进行推理。 1. CMake的安装与配置 下载CMake源码 前往CMake官网下载&#xff0c;找到适合您系统的最新版本tar.gz文件链接&#xff0c;或者直接通过wget下载&#xff1a;CMake官方…

AI数字人系统源码部署解决方案!!!

一、开场白 如今&#xff0c;科技的步伐越来越快&#xff0c;数字人已经从想象中走进了我们的现实生活。它们在娱乐、教育、医疗等多个领域大放异彩。了解数字人的代码开发技术&#xff0c;能让我们更好地理解其工作原理&#xff0c;为那些想在这一领域大展拳脚或者用数字人技…

W803|联盛德|WM IoT SDK2.X测试|(1)开箱:开发板及说明

前几天关注的联盛德微电子新推出了WM IoT SDK2.X&#xff0c;正式发布后&#xff0c;邀请用户参加“免费试用&#xff0c;赢千元大礼”活动&#xff0c;填写信息&#xff0c;等待统一发送&#xff0c;很快收到了板子。 活动地址&#xff1a;联盛德微电子WM IoT SDK2.X正式发布…

2.✨java练习1(熟悉“类”)

1. A B - AcWing题库 问题描述 输入两个整数&#xff0c;求这两个整数的和是多少。 输入格式 输入两个整数A,B&#xff0c;用空格隔开 输出格式 输出一个整数&#xff0c;表示这两个数的和 数据范围 0≤A,B≤1e8 C #include <iostream> // 包含标准输入输出库 using n…

基本网络安全的实现

基本网络安全的实现 一 &#xff1a;AAA AAA 是Authentication&#xff0c;Authorization and Accounting&#xff08;认证、授权和计费&#xff09;的简 称&#xff0c;它提供了一个用来对认证、授权和计费这三种安全功能进行配置的一致性框架&#xff0c; 它是对网络安全…

快手前端通用静态托管服务KFX演进历程:从崎岖土路到平坦高速

快手静态部署托管服务&#xff08;KFX&#xff09;历经四年发展&#xff0c;经历了三个阶段&#xff0c;一步步从勉强能行车的“崎岖土路”到现在多车道并行的“平坦高速”&#xff0c;这一转变极大地提升了资源利用率和效率&#xff0c;满足业务的实际需要。本文将带你了解其背…

Locale+Jackson导致Controller接口StackOverflowError异常解决

问题 由于参与的项目有出海需求&#xff0c;即需要给外国人使用&#xff0c;即&#xff1a;需要支持i18n&#xff08;Internationalization的缩写&#xff0c;共20个字母&#xff0c;除去首尾两个字母&#xff0c;中间有18个&#xff0c;故简称i18n&#xff09;。 本来是好的…

安卓工控平板电脑在环境监测设备中的运用

安卓工控平板电脑在环境监测设备中的运用主要体现在以下几个方面&#xff1a; 一、耐用性与可靠性 安卓工控平板电脑通常具有坚固耐用的外壳设计&#xff0c;如铝合金面板和镀锌钢板箱体结构&#xff0c;能够抵抗高温、低温、湿度、震动等恶劣的工作环境。这种耐用性和可靠性…