FormData可以做些什么事,除了文件上传当然还有文件分片上传呀

简介: FormData 是一个用于表单数据的键值对,可以通过 FormData 对象来模拟表单提交,也可以通过 FormData 对象来实现文件上传。

FormData是一个用于表单数据的键值对,可以通过FormData对象来模拟表单提交,也可以通过FormData对象来实现文件上传。

1. 简单认识

FormData提供了一种表示表单数据的键值对构造方式,可以轻松的将数据通过XMLHttpRequest.send()
方法发送到服务器,如果送出时的编码类型被设为 multipart/form-data,它会使用和表单一样的格式。

最常见的使用场景就是文件上传,但是FormData还可以使用到其他的场景,比如模拟表单提交。

2. 使用

2.1 构造函数

FormData是一个构造函数,它可以接受一个可选的参数,但是在现代浏览器中,它只接受一个HTMLFormElement
对象,如果传入其他类型的参数,会抛出一个TypeError错误。

const formData = new FormData();

or


<form id="form">
    <input type="text" name="name" value="张三">
    <input type="text" name="age" value="18">
</form>

<script>
    const form = document.getElementById('form');
    const formData = new FormData(form);
</script>

注意:表单项的name属性是必须的,否则FormData对象中不会包含该表单项。

2.2 方法

方法 描述
append() 添加一个键值对到FormData对象中
delete() 删除一个键值对
get() 获取一个键值对的值
getAll() 获取一个键值对的所有值
has() 判断FormData对象中是否包含某个键值对
set() 设置一个键值对的值
keys() 返回一个包含所有键名的迭代器
values() 返回一个包含所有键值的迭代器
entries() 返回一个包含所有键值对的迭代器

FormData可以直接使用for...of循环来遍历,也可以使用forEach()方法来遍历。

const formData = new FormData();
formData.append('name', '张三');
formData.append('age', 18);

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

formData.forEach((value, key) => {
   
    console.log(key, value);
});

FormData对象中的键值对是有序的,也就是说,键值对的顺序和添加的顺序是一致的。

同时,FormData对象中的键名是不允许重复的,如果重复添加(append)同一个键名,那么会存在两个同名的键值对。

FormData不可以直接打印,如果直接打印,会打印出一个空对象,如果想要打印出键值对,可以使用for...of循环或者forEach()
方法,打印单个值可以使用get方法。

FormData其实还是很简单的,上面的提供的方法也很简单,直接就见名知意了,所以就不过多的介绍了,下面就来看看它的使用场景。

3. 使用场景

使用场景最常用的就是文件上传了,下面就来看看如何使用FormData来实现文件上传。

3.1 文件上传


<form id="form">
    <input type="file" name="file">
    <button type="submit">提交</button>
</form>

<script>
    const form = document.getElementById('form');
    form.addEventListener('submit', (e) => {
    
        e.preventDefault();
        const formData = new FormData(form);

        const xhr = new XMLHttpRequest();
        xhr.setRequestHeader('Content-Type', 'multipart/form-data');
        xhr.open('POST', '/upload');
        xhr.send(formData);
    });
</script>

上面的代码中,我们使用FormData来构造一个formData对象,然后使用XMLHttpRequest对象来发送请求,这样就可以实现文件上传了。

3.2 表单数据序列化


<form id="form">
    <input type="text" name="name" value="张三">
    <input type="text" name="age" value="18">
    <button type="submit">提交</button>
</form>

<script>
    const form = document.getElementById('form');
    form.addEventListener('submit', (e) => {
    
        e.preventDefault();
        const formData = new FormData(form);
        const params = new URLSearchParams(formData);
        console.log(params.toString());
    });
</script>

以前我们使用jQuery来实现表单数据序列化的时候,需要使用serialize()方法,但是现在我们可以直接使用FormData
对象来实现表单数据序列化了。

URLSearchParamsURL的一个属性,可以用来序列化URL的查询字符串,也可以用来序列化FormData
对象,使用UrlSearchParams.toString()可以将URLSearchParams对象序列化为一个查询字符串,这里不一定非要用FormData

3.3 模拟表单提交

const formData = new FormData();
formData.append('name', '张三');
formData.append('age', 18);

const xhr = new XMLHttpRequest();
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.open('POST', '/submit');
xhr.send(formData);

模拟表单提交一般都是浏览器默认完成的,但是有时候我们需要自己来实现,这时候就可以使用FormData对象来实现了。

4. 文件分片上传

开始上大招了,上面的就是为了凑字数的,下面我们来看看如何使用FormData来实现文件分片上传。

4.1 文件分片上传的原理

文件分片上传的原理就是将一个文件分成多个小文件,然后分别上传,这样就可以实现大文件的上传了。

4.2 文件分片上传的实现

const file = document.getElementById('file').files[0];
const chunkSize = 1024 * 1024 * 2; // 2M
const chunkCount = Math.ceil(file.size / chunkSize);

for (let i = 0; i < chunkCount; i++) {
   
    const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
    xhrFileUpload(chunk, i);
}

function xhrFileUpload(chunk, index) {
   
    const formData = new FormData();
    formData.append('file', chunk);
    formData.append('index', index);

    const xhr = new XMLHttpRequest();
    xhr.setRequestHeader('Content-Type', 'multipart/form-data');
    xhr.open('POST', '/upload');
    xhr.send(formData);
}

上面的代码中,我们使用file.slice()方法来将文件分片,然后使用FormData对象来构造一个formData对象,最后使用XMLHttpRequest对象来发送请求,这样就可以实现文件分片上传了。

当然上面还有一个问题,就是文件分片上传的时候,这里是分为2M一个分片,如果文件太大,那么分片的数量就会很多,这样就会导致请求的数量很多,这样就会导致服务器压力很大,这里是一个优化空间,提示可以使用Web Worker来实现。

5. 总结

FormData对象是一个非常强大的对象,它可以用来构造表单数据,也可以用来模拟表单提交,还可以用来实现文件分片上传,这里只是简单的介绍了一下,更多的内容可以参考MDN

目录
相关文章
|
JavaScript CDN
js:spark-md5分片计算文件的md5值
js:spark-md5分片计算文件的md5值
1855 0
|
12月前
|
JavaScript 前端开发 Android开发
转换 ES6 代码时需要注意哪些兼容性问题
在转换ES6代码时,需关注兼容性问题,如箭头函数、模板字符串、let/const等语法在旧浏览器中的支持情况,以及模块化、类、Promise等特性是否需要polyfill。使用Babel等工具可有效解决大部分兼容性问题。
|
缓存 JavaScript 开发工具
【开发工具】解决webstorm:Loading indexes...
【开发工具】解决webstorm:Loading indexes...
851 0
|
JavaScript 前端开发
vue 部署项目,访问页面空白,找不到js或css文件 (net::ERR_ABORTED 404 (Not Found))
vue 部署项目,访问页面空白,找不到js或css文件 (net::ERR_ABORTED 404 (Not Found))
3503 0
vue 部署项目,访问页面空白,找不到js或css文件 (net::ERR_ABORTED 404 (Not Found))
|
10月前
|
人工智能 Serverless 开发者
最佳实践 | 轻松部署,即刻触达 Qwen2.5 的飞一般的体验
通过阿里云函数计算(FC)部署Ollama和Open WebUI,实现Qwen2.5模型的托管与交互。
|
8月前
|
人工智能 程序员 测试技术
通义灵码 AI 程序员核心功能体验
阿里云通义灵码AI程序员已全面上线,成为全球首个同时支持 VS Code、JetBrains IDEs 开发工具的AI程序员产品。
1135 1
通义灵码 AI 程序员核心功能体验
|
12月前
|
JavaScript 前端开发 数据库
input中的disabled 和 readonly的区别
input中的disabled 和 readonly的区别
432 0
|
存储 测试技术 Python
Python 数组和列表有什么区别?
【8月更文挑战第29天】
2806 4
vue3 键盘事件 回车发送消息,ctrl+回车 内容换行
const textarea = textInput.value.textarea; //获取输入框元素
634 3
|
存储 前端开发 开发者
scss概念及使用
【7月更文挑战第11天】
352 1