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

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

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

正文开始

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

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

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

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

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

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

html 复制代码
<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 而已。下面来看一下用例代码

html 复制代码
<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() 方法打印,如下所示

    js 复制代码
        for (const [key, value] of formData.entries()) {
          console.log(key, value);
        }

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

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

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

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

js 复制代码
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 的领域了, 可以单独封装方法、插件,在本文中不做讨论。


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

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

再见👋🏻

相关推荐
WeiXiao_Hyy23 分钟前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡40 分钟前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone1 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09011 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农1 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king2 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳2 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵3 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星3 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_3 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js