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

相关推荐
Evan芙17 小时前
用fping编写脚本扫描10.0.0.0/24网段在线主机
linux·运维·网络·excel
SamDeepThinking1 天前
基于CompletableFuture的主子任务并行处理架构实战:多渠道账单并发导入性能提升5倍的技术方案
java·后端·excel
SamDeepThinking1 天前
88MB Excel文件导致系统崩溃?看我如何将内存占用降低
java·excel
ChrisitineTX1 天前
警惕数据“陷阱”:Python 如何自动发现并清洗 Excel 中的异常值?
开发语言·python·excel
wtsolutions1 天前
Excel to JSON by WTSolutions 4.0.0 版本更新公告
json·excel·wps·插件·转换·加载项·wtsolutions
wtsolutions1 天前
Excel to JSON by WTSolutions 4.0.0 Update Announcement
json·excel·wps·addin·wtsolutions·conversion
癫狂的兔子2 天前
【Office】【Excel】常用函数公式总结
excel
毛飞龙2 天前
Excel迷你图:在单元格中嵌入趋势洞察
excel·迷你图·sparklines
Tatalaluola2 天前
Unity使用EPPlus读取写入表格
unity·c#·游戏引擎·excel
缺点内向2 天前
如何在 C# 中将 Excel 工作表拆分为多个窗格
开发语言·c#·.net·excel