模板导出和数据导入

1,685 阅读3分钟

前端项目是基于VUE CLI3脚手架来开发的。需求是提供个Excel文档模板,里面有几个字段,来实现模板导出和数据填入然后导入数据库。

对我们前端来说,需要关注的是:

  • 模板是存在前端还是服务器
  • 如何导出
  • 模板数据如何传给接口

至于接口获取到前端传入的文档流,如何解析,还有需要哪些校验之类的,由他们来处理。

模板导出

模板存放在哪里

模板如果存放在服务器,那我们只需要知道具体存放URL即可;那如果存放于前端,我们应该在public文件夹下新建个templates目录来专门存放模板文件。

有了模板位置,如何导出呢?使用a标签

<a href="/templates/xxx.xlsx" download="xxx">模板下载</a>

正常情况下,href属性是导航性的,这里加了个download属性,这样就告诉浏览器不是导航到目标地址,而是将指向的文件下载到本地。

并且download可以给一个值,作为文件下载到本地的文件名。文件存放于项目中,不适合用中文来命名,但下载到本地后,改用中文命名,对用户来说更友好。

数据导入

使用一个type='file'类型的input来承载上传的File文件,但是不可见的,通过change事件来触发接口解析。

<el-button @click="() => $refs.file.click()">数据导入</el-button>
<input
  type="file"
  ref="file"
  style="display:none"
  accept="application/vnd.ms-excel,application/vnd.openxmlformats- 
    officedocument.spreadsheetml.sheet"
  @change="importData"/>

function importData (e) {
  // 二进制
  const formData = new FormData()
  formData.append('file', e.target.files[0])
  axios.post('import_data', formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

虽然这样需求实现了,但有2个疑问?

  • 不能给接口直接传入File吗,而需要FormData来进行包装
  • Content-Type具体用法是什么

FormData

第一个问题,其实HTTP请求并没有限制说不能传递File文件,现在我们需要传输的是Excel文件,MIME类型中存在相关类型:

.xls - application/vnd.ms-excel
.xlsx - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

如果没有其他的限制,可以。但这样传输可能会导致请求数据包过大。

所以我们更常用的FormData,它提供了一种表示表单数据的键值对key/value形式,可以轻松的通过XHR.send()发送出去,且文件会以二进制的形式。

Content-Type

这个字段在请求头或响应头中都可能存在,顾名思义,表示内容的类型。

我们知道,HTTP是应用层协议,虽然它的名称是超文本传输协议,本质上并没有核心传输的功能,它是基于TCP/IP协议来工作的,在TCP/IP协议就相当于快递公司,实现真正的运输工作,不关心你邮寄的是什么。这样包装或拆卸就由我们收发人员来操作,对应到HTTP协议就是在请求头中,我们会告诉底层实体内容的类型,在响应头中的数据是HTTP接收到的处理类型。

重复导入

有个小问题,当我们需要重复导入相同File文件的时候,正常是不会触发的,因为我们用的是change事件,但实际是可以重复导入的,我们刚导入的数据被删除了,或者原模板中存在的数据删除后需要重新导入。

也很简单,我们执行一次导入后就将input值置空。

function importData (e) {
   ...
   e.target.value = ''
   ...
}