文件上传入门指南:前端开发者必须掌握的基础能力

10 阅读4分钟

宝子, 在你前端开发的过程中有没有遇到过文件上传的需求呢?

如果有这样的经历,那么邀请你花一点时间,以批判性的视角审视一下这篇文章。

正文开始

某一天,你在做一个后端管理项目,这时你收到一个需求,要求你的表单可以上传附件。那么, 表单的 input ✨ 就闪亮登场了。

我们只需在 input 中加入 type='file' 就可以使这个输入框变成一个文件选择器。

接着,我们点击文件选择器,选中了要上传的文件,那么我应该如何拿到这个文件呢?

前端的交互大量依赖事件机制,

于是我们要祭出我们的addEventListener。

首先对我们的表单元素进行事件绑定, 对应的事件是 change, 这个事件是用来监听[我们选择文件后确定的动作的], 而他的绑定事件监听器(回调函数)的事件对象(e或者event)中的 target.files 就是存放我们选择文件的数组。因为上传文件可以多选,所以是一个数组格式。代码如下:

<form>
    <input type="file" id="fileInput"/>
</form>
<script>

const fileEl = document.getElementById("fileInput");
fileEl.addEventListener("change", e => {
    const file = e.target.files[0]
})
</script>

此时, 文件[Object file]就已经拿到了, 那么如何传给服务端呢? 为了解决这个问题, new FormData 就要登场了。

new FormData() 是浏览器提供的内置构造函数,用于创建一个 FormData 对象,专门用来封装和管理表单数据的。

FormData 的使用有两种用法。

第一种是直接在 form 表单上设置

<form action="/upload" method="POST" enctype="multipart/form-data">

这样当你的表单 sumbit 的时候浏览器内部会帮你自动构建 FormData 数据并提交, 在此不做过多的讨论。

第二种是我们接下来要使用的方法,即使用 js 来实例化一个 FormData 数据并向服务端提交数据。

用法也很简单抓住两个关键点,一个是 new 实例化, 另一个是 append 的方法 插入数据。

你可以简单的理解为 FormData 就是键值对集合, 而插入数据的方法使用 append 而已。下面来看一下用例代码

<form>
    <input type="file" id="fileInput"/>
</form>

<script>
const fileEl = document.getElementById("fileInput");

fileEl.addEventListener("change", e => {
    const file = e.target.files[0]
    const data = new FormData() // 实例化 FormData
    data.append('file', file) // 将 file 数据添加
})
</script>

使用 FormData 的时候,我觉得有几点需要额外注意一下:

  1. 这个数据格式与 Map 不同, append 插入相同的 key 时, 值不会被覆盖,而是形成数组。 也就是说同一 Key 可以多次 append, 形成数组。

  2. 遍历顺序是顺序保存的。

  3. 允许的值有字符串、Blob、File

  4. 不能用 console.log 直接打印内容,可以使用 entires() 方法打印,如下所示

        for (const [key, value] of formData.entries()) {
          console.log(key, value);
        }
    

然后调用后端给的接口,将数据发送到服务端就完成啦。😉

你以为到这里就结束了吗?

调用接口的时候还是有需要注意的地方的。

以 axios 为例子, 需要注意如下两个细节

export const postFile = (formData) => {
  return http.post('/fs/upload/cos', formData, {
    headers: {
      'Content-Type': 'multipart/form-data',
    },
  })
}

第一,是设置 headers 的 ContentType ; 第二还是设置 headers 的 ContentType。

这里有消息说, axios 可以自动处理,亲爱的读者,你觉得会不会呢?

总结一下:

  1. 以 input 为入手点, 设置 type=file, 设置 id 用来绑定事件
  2. 绑定 input 的 change 事件, 在事件监听器中取到需要上传的文件 e.target.files ← 再次提醒: 这是个数组哦
  3. 实例化 new FormData , 插入数据 append('file', file) , 为提交前做准备
  4. 调用接口,比如 post → URL → data 参数→ 设置 headers 的 Content-Type' 为 'multipart/form-data'

至此文件上传的逻辑就告一段落了,

无论是写原生 JS ,还是用第三方UI组件库,把握住 target.files 和 new FormData 两个点就可以掌握文件上传技术并灵活运用了。

至于文件大小、格式校验,就属于 validate 的领域了, 可以单独封装方法、插件,在本文中不做讨论。


感兴趣的小伙伴可以留言、点赞、提问、批评💐

关注我,下一篇我们聊聊后端如何接收这份数据

再见👋🏻