使用JavaScript,使用FormData和单个XMLHttpRequest上载多个表单

3
假设我有两个结构相同但末尾值不同的表单。我想使用FormData和单个XMLHttpRequest请求提交它们两个。我试图添加另一个FormData对象或额外的数组,但目前结果是空响应。
HTML
<!-- first form -->
<form enctype="multipart/form-data" method="post" action="/" >
  <input type="hidden" name="entity" value="1" />
  <input type="text" name="name" value="" />
  <input type="text" name="email" value="" />
  <input type="password" name="password" value="" />
  <input type="file" name="file[]" multiple />
</form>

<!-- second form -->
<form enctype="multipart/form-data" method="post" action="/" >
  <input type="hidden" name="entity" value="1" />
  <input type="text" name="name" value="" />
  <input type="text" name="email" value="" />
  <input type="password" name="password" value="" />
  <input type="file" name="file[]" multiple />
</form>

JavaScript

var a = new FormData(); // using additional FormData object
var b = [];             // using an array
for(var i = 0; i < document.forms.length; i++){
  var form = document.forms[i];
  var data = new FormData(form);
  if(typeof form['file'] !== 'undefined'){
    for(var j=0; j<form['file'].files.length; j++){
      data.append('file[]', form['file'].files[j]);
    }
  }
  a.append(i, JSON.stringify(data)); // or a.append(i, data);
  b[i] = JSON.stringify(data);       // or b[i] = data;

}
var xhr = new XMLHttpRequest();
var url = "ajax.php";
xhr.open("POST", url, true);
xhr.onreadystatechange = function (){
  if(xhr.readyState == 4 && xhr.status == 200){
    console.log(xhr.responseText);
  }
}
xhr.send(a); // or xhr.send(b); 

PHP

echo json_encode(array_merge($_GET, $_POST, $_FILES));
// or
print_r(array_merge($_GET, $_POST, $_FILES));

@KevinB 你有注意到那个 and 语句旁边的注释部分吗?由于我无法让它正常工作,所以尝试了所有非常规的事情。希望你在给我点踩之后感觉很开心! - hex494D49
我的意思是,是啊,那些都没有意义,文档已经非常清楚地说明了可以传递什么参数进入该方法。我不太确定为什么会尝试使用那些参数,考虑到文档的内容。请参考文档 - Kevin B
1个回答

5
您有几个问题需要解决。其中一个问题是您的输入名称为file[]而不是file,所以您需要使用该名称。另一个问题是如果您想要将文件发送到服务器,则不能使用JSON.stringify
检查我对您代码所做的更改,它将实现您想要的功能:

var a = new FormData(); // using additional FormData object
var b = [];             // using an array
for(var i = 0; i < document.forms.length; i++){
    var form = document.forms[i];
    var data = new FormData(form);
    var formValues = data.entries()
    while (!(ent = formValues.next()).done) {

        // Note the change here 
        a.append(`${ent.value[0]}[]`, ent.value[1])
    }
}
// here a will include all the data from all of your forms.
<!-- first form -->
<form enctype="multipart/form-data" method="post" action="/" >
  <input type="hidden" name="entity" value="1" />
  <input type="text" name="name" value="" />
  <input type="text" name="email" value="" />
  <input type="password" name="password" value="" />
  <input type="file" name="file[]" multiple />
</form>

<!-- second form -->
<form enctype="multipart/form-data" method="post" action="/" >
  <input type="hidden" name="entity" value="1" />
  <input type="text" name="name" value="" />
  <input type="text" name="email" value="" />
  <input type="password" name="password" value="" />
  <input type="file" name="file[]" multiple />
</form>


首先,感谢您花费时间。我仍然只得到一个数组。但是,所有上传的文件(来自两个表单)都在这里,但是我可以看到,第二个表单的值正在覆盖第一个表单的值;换句话说,我没有得到两个数组。 - hex494D49
你永远不会得到两个数组,因为你的字段名称相同,因为它们在后端被覆盖了。我会更新答案,这样你就可以在后端拥有两个数组。 - Dekel
检查 while 循环内的变化。 - Dekel
非常感谢!现在我将尝试添加其他表单元素,如选择框、单选框和复选框数组。希望一切顺利。 - hex494D49

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接