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

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

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

正文开始

某一天,你在做一个后端管理项目,这时你收到一个需求,要求你的表单可以上传附件。那么, 表单的 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 的领域了, 可以单独封装方法、插件,在本文中不做讨论。


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

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

再见👋🏻

相关推荐
kyriewen4 小时前
别再 console.log 了:5 个 Chrome DevTools 调试技巧,用过就回不去了
前端·javascript·面试
IT_陈寒6 小时前
Python搞不定字符串编码?这破玩意坑我两小时!
前端·人工智能·后端
To_OC6 小时前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
DigitalOcean7 小时前
Laravel 开发者已在 DigitalOcean 上开通超过 10 万台服务器
前端·laravel
星始流年7 小时前
从 Tool 到 Skill——基于 LangChain 的服务端Skill实现
前端·langchain·agent
李惟7 小时前
开源本地通信库,纯客户端 RPC,像聊天一样通信
前端
YAwu117 小时前
深入解析 React 炫彩鼠标跟随标题组件:从坐标定位到动画性能
前端·react.js
GuWenyue7 小时前
排序效率低?5分钟吃透快速排序,性能飙升至O(nlogn)
前端·javascript·面试
OpenTiny社区7 小时前
🎨 看完 GenUI SDK 源码我悟了!
前端·vue.js·github
叁两7 小时前
前端转型AI Agent该如何学习?(前置篇)
前端·人工智能·node.js