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

目录

一、需求背景

二、落地实现

1.文件上传

图片示例

HTML代码

业务代码

2.文件下载

图片示例

方式一:代码

方式二:代码

3.文件预览

图片示例

方式一:代码

方式二:代码


一、需求背景

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

二、落地实现

1.文件上传

图片示例

HTML代码

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。

业务代码

javascript 复制代码
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>即可

方式一:代码

javascript 复制代码
<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对象实现的话,则自定义按钮,触发方法去调用。(详情请看方式二)

方式二:代码

javascript 复制代码
<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中额外添加一个路由映射

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

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

bash 复制代码
npm install @vue-office/excel vue-demi

方式一:代码

入口代码

javascript 复制代码
<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'
    };
  },
}

页面代码

bash 复制代码
<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对象打开的话。(详情请看方式二)

方式二:代码

入口代码

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

页面代码

javascript 复制代码
<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文件,修改对应的格式即可。

相关推荐
用户298698530149 小时前
React 项目中灵活管理 Excel 工作表:增删与移动
javascript·react.js·excel
程序猿乐锅1 天前
【苍穹外卖 Day12| Excel 入门】
excel
用户298698530141 天前
Python 数据处理:XML 与 Excel 互转的实用指南
后端·python·excel
xiaopai9452 天前
采购系统和Excel表格区别:钢结构项目物资管理的真实较量
excel·建米软件·采购系统
协享科技2 天前
2026 年 AI 表格工具怎么选:ChatGPT、原生 Copilot/Gemini 与公式助手
人工智能·chatgpt·excel·copilot
用户298698530142 天前
前端实战:在 React 中使用 JavaScript 一键导出 Excel 图表与形状为图片
javascript·react.js·excel
Q一件事2 天前
arcpy实现分区统计到一张excel中
excel
AI刀刀2 天前
deepseek 内容粘贴后符号丢失怎么办?AI 导出鸭实测解决排版乱码问题
android·人工智能·excel·ai导出鸭
圣光SG3 天前
Excel 函数大全
算法·excel
小小的木头人4 天前
Python 批量解析 Excel 经纬度,调用高德地图 API 获取中文地址
开发语言·python·excel