前端项目是基于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 = ''
...
}