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 应用服务中间件
multer实现文件上传功能全解(form上传、fetch请求上传、多文件上传)
multer实现文件上传功能全解(form上传、fetch请求上传、多文件上传)
multer实现文件上传功能全解(form上传、fetch请求上传、多文件上传)
|
存储 JSON 前端开发
前端下载文件以及上传图片预览,顺便了解arrayBuffer和blob
前端下载文件以及上传图片预览,顺便了解arrayBuffer和blob
1133 0
|
5月前
|
JSON 前端开发 JavaScript
前端上传文件前校验文件数据
该文介绍了如何在Vue项目中实现批量导入Excel数据的校验。使用Element UI的`el-upload`组件上传文件,通过FileReader读取内容,结合XLSX库解析Excel为JSON。解析过程包括将二进制数据转换为workbook对象,提取worksheet并转化为JSON。之后,遍历JSON数据进行字段校验,若发现空值则记录错误。提供的Demo展示了选择Excel文件后控制台显示校验结果。技术栈包括vue 2.6.14、element ui 2.15.14和xlsx 0.17.0。建议将此类功能封装为通用组件以复用。
88 2
前端上传文件前校验文件数据
视频文件上传接口上传不了,怎样解决??
视频文件上传接口上传不了,怎样解决??
|
6月前
|
前端开发 NoSQL Redis
如何实现大文件上传:秒传、断点续传、分片上传
如何实现大文件上传:秒传、断点续传、分片上传
470 0
|
6月前
|
移动开发 前端开发
VForm3的文件上传方式
VForm3的文件上传方式
170 0
|
6月前
大文件分片上传,断点续传,秒传 示例(待更新...)
大文件分片上传,断点续传,秒传 示例(待更新...)
|
12月前
layui上传组件连续上传同一个文件upload组件无反应
layui上传组件连续上传同一个文件upload组件无反应
308 0
|
12月前
|
前端开发 JavaScript PHP
在多文件上传中,如何处理文件大小限制?
在多文件上传中,如何处理文件大小限制?
117 0
|
存储 前端开发 NoSQL
注册java实现文件分片上传并且断点续传
一、简单的分片上传 针对第一个问题,如果文件过大,上传到一半断开了,若重新开始上传的话,会很消耗时间,并且你也并不知道距离上次断开时,已经上传到哪一部分了。因此我们应该先对大文件进行分片处理,防止上面提到的问题。