使用formData()上传多个文件

140
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "uph.php");
xhr.send(fd);

uph.php:

var_dump($_FILES['fileToUpload']);

这个方法可行,但仅适用于files[0]。如何使其适用于选择的文件?

我尝试删除[0],但没有成功。

20个回答

146
你必须在JavaScript中使用files.length来追加,然后通过Ajax请求发送它:
var files = document.getElementById('fileToUpload').files;
for (var x = 0; x < files.length; x++) {
    fd.append("fileToUpload[]", files[x]);
}

PHP:

$count = count($_FILES['fileToUpload']['name']);
for($i = 0; $i < $count; $i++){
    echo 'Name: '.$_FILES['fileToUpload']['name'][$i].'<br/>';
}

1
对我没用。我猜这取决于你的多部分表单在服务器端如何处理。 - user4164128
35
根据MDN的说明,“与常规表单数据一样,您可以附加具有相同名称的多个值。例如(通过在名称后添加[]以兼容PHP的命名约定):”。请参见示例3。 - 0xcaff
3
fileToUpload[] is wrong, should be fileToUpload - Houssam Badri
1
在我的情况下,fileToUpload 不起作用。正如答案中建议的那样,它应该是 fileToUpload[]。你的评论让我花了一个小时才弄清楚发生了什么。 - Andre W.
1
@UXAndre 很抱歉,但我是根据我的实际情况进行评论的。 - Houssam Badri
显示剩余2条评论

103

使用 JavaScript 的方法:

var data = new FormData();

$.each($("input[type='file']")[0].files, function(i, file) {
    data.append('file', file);
});

$.ajax({
    type: 'POST',
    url: '/your/url',
    cache: false,
    contentType: false,
    processData: false,
    data : data,
    success: function(result){
        console.log(result);
    },
    error: function(err){
        console.log(err);
    }
})

如果您多次调用data.append('file', file),则请求将包含文件数组。

来自MDN web文档

"FormData 接口的 append() 方法在 FormData 对象中追加新值到现有键名,若键名不存在则添加该键,与 FormData.set 不同之处在于,如果指定的键已经存在,FormData.set 会用新值覆盖所有现有值,而 append() 则会将新值附加到现有值集合的末尾。"

我使用 Node.js 和多部分处理程序中间件 Multer 获取数据,如下所示:

router.post('/trip/save', upload.array('file', 10), function(req, res){
    // Your array of files is in req.files
}

27
如果您多次调用data.append('file', file),则请求将包含您的文件数组。这节省了我数小时的绝望,特别是因为我认为名称应该是'file[]',但只使用'file'并多次调用也可以,谢谢! - bourgeois247
2
老兄,你真是个传奇,我一早上都在找这个,太感谢了。 - Kannan T
4
我尝试了你的例子,但当我使用var_dump对其进行检测时,它总是返回图片集中的最后一张图片。我将data.append('file', file)更改为data.append('file', i),这对我起作用了。 - Jeroen Bellemans
3
FormData的键设置为files对我而言是可行的,而不是将其显示为数组,例如files[] - djneely
2
对我不起作用。必须执行data.append('file[]', file); - M K Garwa
显示剩余4条评论

28

你只需要使用 fileToUpload[] 而不是 fileToUpload

fd.append("fileToUpload[]", document.getElementById('fileToUpload').files[0]);

它将返回一个包含多个名称、尺寸等的数组...


5
这需要循环,并将每个 files[i] 添加到其中。 - FindOutIslamNow

27

这对我有用:

let formData = new FormData()
formData.append('files', file1)
formData.append('files', file2)

4
需要进行循环追加文件。 - ashish bansal

11

这个方法对我有效

//Javascript part
//file_input is a file input id
var formData = new FormData();
var filesLength=document.getElementById('file_input').files.length;
for(var i=0;i<filesLength;i++){
 formData.append("file[]", document.getElementById('file_input').files[i]);
}
$.ajax({
   url: 'upload.php',
   type: 'POST',
   data: formData,
   contentType: false,
   cache: false,
   processData: false,
   success: function (html) {
   
  }
});

<?php
//PHP part
$file_names = $_FILES["file"]["name"];
for ($i = 0; $i < count($file_names); $i++) {
   $file_name=$file_names[$i];
   $extension = end(explode(".", $file_name));
   $original_file_name = pathinfo($file_name, PATHINFO_FILENAME);
   $file_url = $original_file_name . "-" . date("YmdHis") . "." . $extension;
 move_uploaded_file($_FILES["file"]["tmp_name"][$i], $absolute_destination . $file_url);
}


8

在向文件描述符(fd)追加数据时,使用[]是有效的。但如果您希望将数据按文件分组,则建议以以下方式执行:

var files= document.getElementById('inpFile').files
var fd = new FormData()

for (let i = 0; i < files.length; i++) {
  fd.append(i, files[i])
}

现在,您的数据将按文件分组发送,而不是按属性分组。

5
这个很好!
var fd = new FormData();

$('input[type="file"]').on('change', function (e) {
    [].forEach.call(this.files, function (file) {
        fd.append('filename[]', file);
    });
});

$.ajax({
    url: '/url/to/post/on',
    method: 'post',
    data: fd,
    contentType: false,
    processData: false,
    success: function (response) {
        console.log(response)
    },
    error: function (err) {
        console.log(err);
    }
});

在你的代码中添加一个简短的解释会使答案更好!这只是一个有用的提示。 - chevybow

5

我曾经做过以下的工作:

var images = document.getElementById('fileupload').files;
var formData = new FormData();
for(i=0; i<images.length; i++) {
     formData.append('files', images[i]);
}

5

这对我有用

var ins = $('.file').map(function () {
    return this.files;
}).get();

for (var x = 0; x < ins; x++) {
    formData.append("file", ins[x][0]);
}

4
如果您已经将表单作为构造函数参数实例化了FormData对象,则输入文件的name属性必须包含方括号。
HTML:
<form id="myForm" method="POST" action="url" enctype="multipart/form-data">
<input class="form-control form-control-lg" type="file" name="photos[]" multiple />

JS:

var formData = new FormData(document.getElementById('myForm'));
console.log(formData.getAll('photos[]'));

这对我有用!


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