(3)
filename:
可选。
传给服务器的文件名称 (一个
USVString
),当一个
Blob
或
File
被作为第二个参数的时候,
Blob
对象的默认文件名是 "blob"。
File
对象的默认文件名是该文件的名称。(注意: 如果你指定一个
Blob
作为数据添加到
FormData
对象中, 文件名会被放在 "Content-Disposition" 头部(常常会根据浏览器变化而变化)传给服务器。)
第三个参数
filename
之前确实没用过,得注意一下,今天也是看到这个第 3 个参数,所以决定研究一下。
二、FormData 常用方法
1、创建 FormData 对象
// 1、创建一个空对象
var formData = new FormData();
// 2、使用已有表单来初始化对象
//表单示例
<form id="myForm" action="" method="post">
<input type="text" name="name">名字
<input type="password" name="psw">密码
<input type="submit" value="提交">
</form>
//方法示例
// 获取页面已有的一个form表单
var form = document.getElementById("myForm");
// 用表单来初始化
var formData = new FormData(form);
// 我们可以根据name来访问表单中的字段
var name = formData.get("name"); // 获取名字
var psw = formData.get("psw"); // 获取密码
// 当然也可以在此基础上,添加其他数据
formData.append("token","kshdfiwi3rh");
2、操作方法
// 1、获取值:通过get(key)/getAll(key)来获取对应的value
formData.get("name"); // 获取key为name的第一个值
formData.getAll("name"); // 返回一个数组,获取key为name的所有值
// 2、添加数据:通过append(key, value)来添加数据
// 如果指定的key不存在则会新增一条数据,如果key存在,则添加到数据的末尾
formData.append("k1", "v1");
formData.append("k1", "v2");
formData.get("k1"); // "v1"
formData.getAll("k1"); // ["v1","v2","v3"]
// 3、设置修改数据:set(key, value)来设置修改数据
// 如果指定的key不存在则会新增一条,如果存在,则会修改对应的value值
formData.append("k1", "v1");
formData.set("k1", "1");
formData.getAll("k1"); // ["1"]
// 4、判断是否存在对应数据:has(key)来判断是否对应的key值
formData.has("k1"); // true
// 5、删除数据
formData.delete("k1");
三、formData.append() 遇到的问题
1、formData使用append追加后console仍为空的问题
formData.append('image_url', files[0]);
console.log(formData)
解决:需要用
formData.get("键")
的方法获取值。
let formData = new FormData();
formData.append('image_url', files[0]);
console.log(formData.get('image_url'))
2、formData.append("files",filesArray) 添加文件无效的问题
选择多个文件一起上传,就参考选用了FormData实例通过append方法添加文件并发送,原代码是这么写的:
let formData = new FormData();
formData.append("files",this.createOperation.fileList);
这种以数组形式append的方式具有以下特征:
(1)append之后,调试发现formData为空,查阅资料得知formData需要使用FormData.get,FormData.getAll,FormData.keys等方法访问其内部的键值对。
(2)浏览器network调试面板中可看到发送的files参数为[object file]形式,而正确的形式应该是[binary]
解决方案:
分多次向formData中同一个键名下添加一个文件即可。
this.createOperation.fileList.map(element => {
formData.append("files", element);
四、使用 FormData 传文件流,传 json 数组对象(重点)
关于 FormData.append() 的参数,这里要注意下 value 字段,如果你要填入的是一个对象,会将它转换成字符串,也就是最后传给后台的都是 [object object]
,这样后台当然是无法解析的。下边举个例子,大家就明白了
var json=[
{'name':'小明','age':15,'skills':['抽烟','喝酒','烫头'],'family':{'father':'大明','mohter':'小红'}},
{'name':'胖虎','age':17,'skills':['打架','打架','还是打架'],'family':{'father':'佐藤','mohter':'爱田'}},
首先我们先试一下,把小明的family对象传给后台。
var data=new FormData()
data.append('family',json[0].family)
结果被解析成了object object,有人该说了,你把它用 JSON.stringify
序列化之后不就行了,然后后端配合,再解码成json,对,这样确实行,但不要忘了,咱们还是需要传文件流的,文件流被序列化之后会被转化成一个空对象,这样后台就无法识别。由于时间原因,这里就不演示反面案例了。这里我们要用两个语法:
1、a['b'] 等于 a.b
2、c[0] 取得是c数组的第一项
正确方法:
var data=new FormData()
for(var i=0,len=json.length;i<len;i++){
data.append('json['+i+'][name]',json[i].name)
data.append('json['+i+'][age]',json[i].age)
data.append('json['+i+'][family][father]',json[i].family.father)
data.append('json['+i+'][family][mother]',json[i].family.mohter)
for(var j=0,len2=json[i].skills.length;j<len2;j++){
data.append('skills['+i+']['+j+']',json[i].skills[j])
$.ajax({
url:'demo.php',
type: "Post",
dataType: "json",
cache: false,//上传文件无需缓存
processData: false,//用于对data参数进行序列化处理 这里必须false
contentType: false, //必须
data:data,
success:function (res) {
console.log(res);
error:function (error) {
console.log(error);
之后,我们再给小明和胖虎每人上传一张个人写真照(利用input file,文件流),这里我们利用input上传时的file对象,附上代码:
<input type="file" id="upload">
$('#upload').on('change',function (e) {
var file = e.target.files[0];
console.log(file);
data.append('json[0][image]',file)
这里需要注意的是:如果是继续上传照片,还是在这个字段 'json[0][image]' 里去 append file。如第 3 讲第 2 个问题。
这个 file 对象是一个含有二进制文件,这个对象如果直接序列化,会被转化为一个空对象,后台无法识别。所以如果有特殊的文件之类的,那就无法使用 JSON.stringify
序列化去传参数了。