Vue - 使用Element UI Upload / importExcelJs进行文件导入

1 情景一

需求背景后端配合,点击"导入"按钮,弹出“导入”弹窗,将电脑本地Excel表格数据导入到页面中表格位置(需要调用后端接口),而页面中表格通过后端接口获取最新数据。
实现思路:弹窗嵌入 Element UI Upload 上传组件,获取到文件后调后端接口。

action: 上传的地址
file-list: 上传的文件列表, 例如: [{name: ‘food.jpg’, url: ‘https://xxx.cdn.com/xxx.jpg’}]
headers: 设置上传的请求头部(上传的文件可能是有固定格式的(表头),这个是在后端设定好了的,所以如果上传的文件格式不对可能会引起报错。)
before-upload: 上传文件之前的钩子,可作上传之前校验
on-error: 文件上传失败时的钩子
on-exceed: 文件超出个数限制时的钩子
on-success: 文件上传成功时的钩子
on-change: 文件状态改变时的钩子
this.$refs.fileUpload.submit(): 手动上传文件列表(fileUpload是自定义的名字)

  • 组件代码
<template><span><el-buttonplainicon="el-icon-upload2"type="primary"size="mini":disabled="disabled"@click="importFile">{{ $t('import') }}</el-button><el-dialogv-if="open":title="importTitle":visible.sync="open"width="500px"append-to-body:close-on-click-modal="false":show-close="false"@close="cancel"><div v-if="isShowRecord" class="record-btn"><el-button icon="el-icon-time" type="primary" size="mini" @click="recordBtnClick"><span>{{ recordText }}</span></el-button></div><div style="text-align: center;"><el-uploadref="fileUpload"multiple:auto-upload="false":action="uploadFileUrl":before-upload="handleBeforeUpload":file-list="fileList":limit="limit":on-error="handleUploadError":on-exceed="handleExceed":on-success="handleUploadSuccess":on-change="handleChange":headers="headers"class="upload-file-uploader"><div style="border:1px dashed #e9e9e9"><i class="el-icon-plus avatar-uploader-icon" style="margin:80px;font-size: 25px;" /></div><!-- 上传提示 --><div v-if="showTip" slot="tip" class="el-upload__tip">{{ $t("pleaseUpload") }}<template v-if="fileSize">{{ $t("sizeLess") }}<b style="color: #f56c6c">{{ fileSize }}MB</b></template><template v-if="fileType">{{ $t("formatIs") }}<b style="color: #f56c6c">{{ fileType.join("/") }}</b></template>{{ $t("file") }}</div></el-upload></div><div class="template"><!-- <form v-show="false" id="templateForm" :action="templateUrl" method="get" /> --><span @click="downloadFile">{{ $t("downloadThisTemplate") }}</span></div><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitForm">{{ $t('confirm') }}</el-button><el-button @click="cancel">{{ $t('cancel') }}</el-button></div></el-dialog></span>
</template>
<script>
import { getToken } from '@/utils/auth'
import { downloadGet } from '@/utils/request'
import moment from 'moment'
import $ from '@/i18n/index'export default {name: 'FileImport',props: {// 是否禁用导入按钮disabled: {type: Boolean,default: false},// 导入弹窗标题importTitle: {type: String,default: () => {return $.t('fileImport')}},// 数量限制limit: {type: Number,default: 1},// 大小限制(MB)fileSize: {type: Number,default: 20},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ['csv']},// 是否显示提示isShowTip: {type: Boolean,default: true},// 下载模板路径downLoadUrl: { type: String, default: null },// 下载的全拼路径fullPathUrl: { type: String, default: null },// 模板名称fileName: { type: String, default: moment().format('yyyyMMDDHHmmss') },// 导入数据路径importUrl: { type: String, default: null },// 是否展示导入导出记录按钮isShowRecord: {type: Boolean,default: false},// 导入导出记录文字recordText: {type: String,default: () => {return $.t('importAndExportRecord')}}},data() {return {open: false,number: 0,baseUrl: process.env.VUE_APP_BASE_API,// templateUrl://   this.fullPathUrl || process.env.VUE_APP_BASE_API + this.downLoadUrl,fileList: []}},computed: {headers() {return { Authorization: getToken() }},// 是否显示提示showTip() {return this.isShowTip && (this.fileType || this.fileSize)},// 上传文件服务器地址uploadFileUrl() {return process.env.VUE_APP_BASE_API + this.importUrl}// templateUrl() {//   return this.fullPathUrl || process.env.VUE_APP_BASE_API + this.downLoadUrl// }},methods: {importFile() {this.open = true},submitForm() {if (this.fileList.length === 0) {this.$modal.msgError(this.$t('pleaseImportFile'))return}this.$refs.fileUpload.submit()},cancel() {this.$refs.fileUpload.clearFiles()this.open = falsethis.$emit('importSuccess')},// 上传前校检格式和大小handleBeforeUpload(file) {// 校检文件类型if (this.fileType) {const fileName = file.name.split('.')const fileExt = fileName[fileName.length - 1]const isTypeOk = this.fileType.indexOf(fileExt) >= 0if (!isTypeOk) {this.$modal.msgError(`${this.$t('fileTypeErrorUpload')}${this.fileType.join('/')}${this.$t('file')}`)return false}}// 校检文件大小if (this.fileSize) {const isLt = file.size / 1024 / 1024 < this.fileSizeif (!isLt) {this.$modal.msgError(`${this.$t('uploadFileSizeLess')} ${this.fileSize} MB!`)return false}}this.$modal.loading(this.$t('waitForUpload'))this.number++return true},// 文件个数超出handleExceed() {this.$modal.msgError(`${this.$t('uploadFileNumberLess')} ${this.limit}`)},// 上传失败handleUploadError() {this.$modal.msgError(this.$t('uploadFail'))this.$modal.closeLoading()},// 上传成功回调handleUploadSuccess(res, file) {if (res.code === 0) {this.$message({ type: 'success', message: this.$t('uploadSuccess') })this.cancel()this.$emit('handleUploadSuccess')} else {this.number--this.$modal.msgError(res.msg)this.$refs.fileUpload.handleRemove(file)}this.$modal.closeLoading()},downloadFile() {// document.getElementById('templateForm').submit()let dowloadUrl = this.downLoadUrlif (this.fullPathUrl) {dowloadUrl = this.fullPathUrl}downloadGet(dowloadUrl, `${this.fileName}.${this.fileType}`, {})},recordBtnClick() {this.$emit('recordBtnClick')},handleChange(file, fileList) {this.fileList = fileList}}
}
</script>
<style lang="scss" scoped>
.template {text-align: center;color: #1890ff;padding: 10px;span:hover {cursor: pointer;border-bottom: 1px solid #1890ff;}
}.record-btn {position: absolute;right: 18px;top: 18px;
}
</style>
// 通用下载方法,blob形式
export function downloadGet(url, filename, config) {downloadLoadingInstance = Loading.service({text: '正在下载数据,请稍候',spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.7)'})return service.get(url, {headers: { 'Content-Type': 'application/x-www-form-urlencoded' },responseType: 'blob',...config}).then(async(data) => {const isLogin = await blobValidate(data)if (isLogin) {const blob = new Blob([data])saveAs(blob, filename)} else {const resText = await data.text()const rspObj = JSON.parse(resText)const errMsg =errorCode[rspObj.code] || rspObj.msg || errorCode['default']Message.error(errMsg)}downloadLoadingInstance.close()}).catch((r) => {console.error(r)Message.error('下载文件出现错误,请联系管理员!')downloadLoadingInstance.close()})
}
import Cookies from 'js-cookie'const TokenKey = 'Admin-Token'export function getToken() {return Cookies.get(TokenKey)
}

在这里插入图片描述

  • 使用组件
 <FileImportdown-load-url="/client/template/export_template/sec_type"import-url="/client/sec_type/import"file-name="导入持仓"
/>

在这里插入图片描述

2 情景二

需求背景纯前端实现文件导入的情景。例如,一个常规excel文件填写模板,在用户的电脑上,用户上传完后,还可以在预览展示时,在线修改,改完可以下载,也可以将数据给到服务端,但这时,比如这模板数据通常不多,比如是一个团队成员这样的数据,通过文件流的形式传给后端,可能不是很理想,倒不如前端解析传那几行数据就行。
实现思路importExcel.js 导入excel文件

  1. 使用html支持上传标签从本地获取文件,例如type为file的input,el-upload等。
  2. 利用FileReader将文件读取为二进制字符串。
  3. 使用XLSX插件XLSX.read()方法,将二进制字符串转换成excel文件的工作蒲对象workbook(简写成wb)。
  4. 通过XLSX.utils.sheet_to_json()方法,从wb中获取第一张 Sheets表格数据并将其转换为json数据。
  5. 重组json数据生成数组,即是根据自己的定义的列字段名,重新组成符合自己需求的json数据。因为从excel中提取的数据是没有字段名或字段名不符合要求的,而我们需要渲染在页面表格中又确实需要合适的字段名。
/* eslint-disable */
/* 导入excel文件 */
/*** @param file 文件流* @param tableTemplate 要导入的表格模板,一个数组,如:* tableTemplate: ['userCode', 'userName', 'department', 'major', 'position'],其中的值* 为表格的字段名,注意字段的顺序应与实际的导入excel一致。*/
export default function importExcel (file, tableTemplate) {return new Promise((resolve, reject) => {let f = file.raw // 获取文件内容// 通过DOM取文件数据let rABS = false // 是否将文件读取为二进制字符串let reader = new FileReader()FileReader.prototype.readAsBinaryString = function (f) {let binary = ''let rABS = false // 是否将文件读取为二进制字符串let wb // 读取完成的数据let outdatalet reader = new FileReader()reader.onload = function (e) {let bytes = new Uint8Array(reader.result)let length = bytes.byteLengthfor (let i = 0; i < length; i++) {binary += String.fromCharCode(bytes[i])}let XLSX = require('xlsx')if (rABS) {wb = XLSX.read(btoa(binary), { // 手动转化type: 'base64'})} else {wb = XLSX.read(binary, {type: 'binary'})}outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]) // outdata就是表格中的值let arr = []// 下面是数据解析提取逻辑if (tableTemplate.length > 0) {let tempArr = Object.keys(outdata[0])let tempArrNew = []for (let i in tempArr) {for (let k in tableTemplate) {if (i === k) {tempArrNew.push({fieldE: tableTemplate[k], fieldC: tempArr[i]})}}}tempArr = tempArrNewoutdata.map(item => {let obj = {}tempArr.map(temp2 => {obj[temp2.fieldE] = item[temp2.fieldC]})arr.push(obj)})}resolve(arr)}reader.readAsArrayBuffer(f)}if (rABS) {reader.readAsArrayBuffer(f)} else {reader.readAsBinaryString(f)}})
}

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

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

相关文章

从0到1入门C++编程——01 C++基础知识

文章目录 一、工具安装二、新建项目三、设置字体、注释、行号四、C基础知识1.数据类型2.输入输出3.运算符4.选择、循环结构5.跳转语句6.数组7.函数8.指针9.结构体 一、工具安装 学习C使用到的工具是Visual Studio&#xff0c;Visual Studio 2010旗舰版下载链接&#xff1a;点此…

【python_数据分组】

对excel按照标签进行分组&#xff0c;例如按照“开票主体和对方公司”进行分组&#xff0c;并获取对应的明细。 表格如下&#xff1a; def main(excel_data):result {}for d in excel_data:if str(d[0])str(d[1]) in result:result[str(d[0])str(d[1])].append([d[0],d[1],…

java生产设备效率管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web生产设备效率管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为ac…

在Mac上恢复SD卡数据的 6 个有效应用程序

慌&#xff01;SD卡里的照片和视频不小心删了&#xff0c;Mac设备上还恢复不了数据&#xff01; 遇到这种情况&#xff0c;你需要的是一款可靠的Mac适用的SD卡恢复软件。我们为你准备了一份最佳的SD卡恢复软件列表&#xff0c;并且还有详细的评论。另外&#xff0c;我们还会给…

用katalon解决接口/自动化测试拦路虎--参数化

不管是做接口测试还是做自动化测试&#xff0c;参数化肯定是一个绕不过去的坎。 因为我们要考虑到多个接口都使用相同参数的问题。所以&#xff0c;本文将讲述一下katalon是如何进行参数化的。 全局变量 右侧菜单栏中打开profile&#xff0c;点击default&#xff0c;打开之后…

Big-endian与Little-endian详尽说明

大端与小端存储详尽说明 大端与小端存储详尽说明 大端与小端存储详尽说明一. 什么是字节序二. 什么是大端存储模式三. 什么是小端存储模式四. 大小端各自的特点五. 为什么会有大小端模式之分六. 为什么要注意大小端问题六. 大小端判定程序七. 大端小端的转换1&#xff09;16位大…

EasyExcel实现动态表头(注解实现)

要实现上述动态头&#xff0c;按每日统计&#xff0c;每月统计&#xff0c;每年统计。而时间是一直变化&#xff0c;所以我们需要表头也一直动态生成。 首先&#xff0c;我们需要定义所需要实体类 public class CountDayData {ExcelProperty(value "业务员姓名")p…

初识大数据,一文掌握大数据必备知识文集(7)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

miniqmt配置

1 下载安装qmt 2 将安装目录下的 xtquant 目录复制到 python安装目录 的相同路径下 3 测试 from xtquant import xtdata def on_data (datas):#回调函数 print(datas) seq xtdata.subscribe_whole_quote(code_list[‘002306.SZ’], callbackon_data) time.sleep(10) xtda…

【ES】es介绍,使用spring-boot-starter-data-elasticsearch整合的ES来进行操作Es

文章目录 倒排索引&#xff08;Inverted Index&#xff09;和正排索引&#xff08;Forward Index&#xff09;es和MySQL对比IK分词器的总结mapping映射使用springboot整合的ES来进行操作Es1. 实体类中添加注解2. 编写Repository层3. 通过Repository进行增删改查 倒排索引&#…

【C++】手撕 Vector类

目录 1&#xff0c;vector类框架 2&#xff0c;vector () 3&#xff0c;pinrt() 4&#xff0c;vector(int n, const T& value T()) 5&#xff0c;vector(const vector& v) 6&#xff0c;vector(InputIterator first, InputIterator last) 7&#xff0c;~vector…

读书笔记1-C++ Primer Plus

C是在C语言基础上开发的一种集面向对象编程&#xff08;OOP&#xff09;、通用编程和传统的过程化编程于一体的编程语言。本书是根据2003年的ISO/ANSI C标准编写的&#xff0c;通过大量短小精悍的程序详细而全面地阐述了C的基本概念和技术。 全书分17章和10个附录&#xff0c;分…

深度学习——PIL和OpenCV

PIL 官方文档 格式互转 opencv cv2.imread() 参数&#xff1a; filepath&#xff1a;读入imge的完整路径 flags&#xff1a;标志位&#xff0c;{cv2.IMREAD_COLOR&#xff0c;cv2.IMREAD_GRAYSCALE&#xff0c;cv2.IMREAD_UNCHANGED} cv2.IMREAD_COLOR&#xff1a;默认参数&…

Leetcode每日一题:1599.经营摩天轮的最大利润

前言&#xff1a;本题是一道逻辑细节题&#xff0c;考察阅读理解并转化为代码的能力&#xff0c;很多细节 题目描述&#xff1a; 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱&#xff0c;但…

Jetpack Compose中使用Android View

使用AndroidView创建日历 Composable fun AndroidViewPage() {AndroidView(factory {CalendarView(it)},modifier Modifier.fillMaxWidth(),update {it.setOnDateChangeListener { view, year, month, day ->Toast.makeText(view.context, "${year}年${month 1}月$…

JSON 详解

文章目录 JSON 的由来JSON 的基本语法JSON 的序列化简单使用stringify 方法之 replacerstringify 方法之 replacer 参数传入回调函数stringify 方法之 spacestringify 方法之 toJSONparse 方法之 reviver 利用 stringify 和 parse 实现深拷贝 json 相信大家一定耳熟能详&#x…

Apache Doris (五十五): Doris Join类型 - Colocation Join

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. Colocation Join原理

Hive讲课笔记:内部表与外部表

文章目录 零、学习目标一、导言二、内部表1.1 什么是内部表1.1.1 内部表的定义1.1.2 内部表的关键特性 1.2 创建与操作内部表1.2.1 创建并查看数据库1.2.2 创建数据表1.2.3 插入表记录1.2.4 通过HDFS WebUI查看数据库与表 三、外部表2.1 什么是外部表2.2 创建与操作外部表2.2.1…

Idea如何从磁盘中应用 下载好的插件流程,安装zip压缩包。

1、将下载的插件文件&#xff08;通常是一个ZIP文件&#xff09;复制到IntelliJ IDEA的“plugins”文件夹中。 IDEA版本 2、重启IntelliJ IDEA。 3、在设置窗口中&#xff0c;选择左侧的“Plugins”。 4、选择之前复制到“plugins”文件夹中的插件文件&#xff0c;点击“OK”按…

【新手向】VulnHub靶场MONEYBOX:1 | 详细解析

MONEYBOX:1 安装靶机 作为一名新手&#xff0c;首先要配置好环境&#xff0c;才能进行下一步的操作。 将下载的ova文件导入VirtualBox。 VirtualBox下载地址&#xff1a;https://www.oracle.com/cn/virtualization/technologies/vm/downloads/virtualbox-downloads.html 选择…