这几天做项目都是个文件流各种打交道,当然其中就免不了和FormData接触了了呀,所以这次仔细研读下FormData类的所有常用的特性,以及总结所用的领域有哪些?
一、案例分析(热身)
在了解FormData之前先来了解一个前端上传多个附件,且能对上传的附件进行删除,后端用express、multer接受处理文件的小案例,此案例涉及的一些技术栈:node、express、fetch、FormData、multer
前端业务核心逻辑:
var formData = new FormData();
files.forEach(v => {
formData.append('files',v,v.name);
});
formData.append('user','ligc');
fetch('/upload',{
method: 'post',
body: formData
}).then(res=> res.json()).then(res=>{
console.log(res);
});
后端核心业务逻辑:
// 获取上传文件
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
cb(null, Math.random().toString().split('.').join('') + '-' + file.originalname)
}
});
const upload = multer({ storage: storage });
app.post('/upload',upload.array('files'), (req,res) => {
res.json({status:200,code:0,data:req.body,message:'上传文件成功'});
});
遇到的问题有哪些?
1.通过express默认的req.files接收为undefined
2.fetch请求不能设置headers的Content-type=multipart/form-data,如果设置,则后端不能接收到文件信息
3.使用multer生成附件的时候,没有文件后缀
4.Express打开网页文件的方式,可以选择express.static的方式打开
参考文档:
https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md
https://juejin.im/post/59eb064d51882578d84e9a39
https://segmentfault.com/a/1190000012918178
https://www.jianshu.com/p/1e92a86c571a
前端所有代码:
多文件上传测试
支持上传多个文件
后端所有代码:
const express = require('express');
const app = express();
const multer = require("multer");
// 获取上传文件
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
cb(null, Math.random().toString().split('.').join('') + '-' + file.originalname)
}
});
const upload = multer({ storage: storage });
app.post('/upload',upload.array('files'), (req,res) => {
res.json({status:200,code:0,data:req.body,message:'上传文件成功'});
});
app.use('/web',express.static('html'));
app.listen(3000, () => {
console.log('server start at port 3000.');
});
二、FormData对象
概述:FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据具有同样形式。
注:FormData 对象的字段类型可以是 Blob, File, 或者 string: 如果它的字段类型不是Blob也不是File,则会被转换成字符串。
(包括文件信息,所有的输入元素都需要有name属性,否则无法访问到值。)
var formElement = document.querySelector("form");
var formData = new FormData(formElement);
var request = new XMLHttpRequest();
request.open("POST", "submitform.php");
formData.append("serialnumber", serialNumber++);
request.send(formData);
(1)append() 方法 * 常用
概述:添加一个新值到 FormData 对象内的一个已存在的键中,如果键不存在则会添加该键。
语法:
formData.append(name, value);
formData.append(name, value, filename);
参数:name -> 表单name,value -> 表单value,filename -> 传给服务器的文件名称 ,当一个 Blob 或 File 被作为第二个参数的时候, Blob 对象的默认文件名是 "blob"。 File 对象的默认文件名是该文件的名称。
示例:
var formData = new FormData(); // Currently empty
formData.append('username', 'Chris');
formData.append('userpic', myFileInput.files[0], 'chris.jpg');
(2)set() 方法
概述:set() 方法会对 FormData 对象里的某个 key 设置一个新的值,如果该 key 不存在,则添加。(set() 和 FormData.append 不同之处在于:如果某个 key 已经存在,set() 会直接覆盖所有该 key 对应的值,而 FormData.append 则是在该 key 的最后位置再追加一个值。)
语法:
formData.set(name, value);
formData.set(name, value, filename);
示例:
var formData = new FormData(); // Currently empty
formData.set('username', 'Chris');
formData.set('userpic', myFileInput.files[0], 'chris.jpg');
(3)get() 方法
概述:FormData的get()方法用于返回FormData对象中和指定的键关联的第一个值,如果你想要返回和指定键关联的全部值,那么可以使用getAll()方法。
语法:
formData.get(name); // 返回值为 键名对应的第一个键值
示例:
var formData = new FormData();
formData.append('username', 'Chris');
formData.append('username', 'Bob');
formData.get('username'); // Returns "Chris"
(4)getAll() 方法
概述:getAll()方法会返回该 FormData 对象指定 key 的所有值。
示例:
var formData = new FormData();
formData.append('username', 'Chris');
formData.append('username', 'Bob');
formData.get('username'); // Returns ["Chris", "Bob"]
(5)entries() 方法
概述:The FormData.entries() 方法返回一个 iterator对象 ,此对象可以遍历访问FormData中的键值对。其中键值对的key是一个 USVString 对象;value是一个 USVString , 或者 Blob对象。
语法:
formdata.entries(); // 返回 iterator
示例:
var formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
// Display the key/value pairs
for(var pair of formData.entries()) {
console.log(pair); // ["key1", "value1"]、["key2", "value2"]
console.log(pair[0]+ ', '+ pair[1]);
}
(6)keys() 方法
概述:FormData.keys() 该方法返回一个迭代器(iterator),遍历了该 formData 包含的所有key ,这些 key 是 USVString 对象。
语法:
formdata.keys(); // 返回一个迭代器( iterator)
示例:
// 先创建一个 FormData 对象
var formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
// 输出所有的 key
for (var key of formData.keys()) {
console.log(key); // key1 key2
}
(7)has() 方法 [ Boolean formData.has(name); ]
示例:
formData.has('username'); // returns false
formData.append('username', 'Chris');
formData.has('username'); // returns true
(8)values() 方法 [ 类似format.keys(),获取所有values ]
(9)delete() 方法 [formData.delete(name); // return undefined; ]
概述:delete() 方法 会从 FormData 对象中删除指定 key 和它对应的 value(s)。