在 javascript 中的 FormData 中发送文件列表

Posted

技术标签:

【中文标题】在 javascript 中的 FormData 中发送文件列表【英文标题】:Send FileList in FormData in javascrirpt 【发布时间】:2022-01-09 15:27:13 【问题描述】:

我正在尝试使用 FormData 发送一堆图像,但当然,我无法发送 FileList,而且我未能找到发送这些文件的方法。我已经尝试自己寻找答案,但大多数人建议附加每个文件。

for (let i = 0 ; i < images.length ; i++) 
    formData.append("images[]", images[i]);

但它最终只有 formData 中的最后一个文件,由于某种原因,以前的文件正在被下一个文件替换。

我也尝试将 FileList 转换为一个数组,这可行,但我不知道如何分隔这些文件,现在每个文件都在一个键中作为字符串。

0: "[\"lastModified\":1606255989000,\"lastModifiedDate\":\"undefined\",\"name\":\"logo.png\",\"size\":54438,\"type\":\"image/png\",\"lastModified\":1606255979000,\"lastModifiedDate\":\"undefined\",\"name\":\"logo1.png\",\"size\":58023,\"type\":\"image/png\",\"lastModified\":1606252752000,\"lastModifiedDate\":\"undefined\",\"name\":\"logo2.png\",\"size\":28147,\"type\":\"image/png\",\"lastModified\":1606255121000,\"lastModifiedDate\":\"undefined\",\"name\":\"logo3.png\",\"size\":18260,\"type\":\"image/png\"]"

我可以将其转换为字符串并使用 作为每个条目的结尾将其剪切为自己的键。我不想这样做,即使我的经验很少,我也知道这不是一个好方法。

到目前为止,我的 javascript 代码如下所示。

 File.prototype.toObject = function () 
  return Object(
    lastModified: parseInt(this.lastModified),
    lastModifiedDate: String(this.lastModifiedDate),
    name: String(this.name),
    size: parseInt(this.size),
    type: String(this.type)
    )
  

  FileList.prototype.toArray = function () 
    return Array.from(this).map(function (file) 
      return file.toObject()
    )
  

  let files = document.getElementById('files').files

  let filesArray = files.toArray();

  let formData = new FormData();

  formData.append('images[]', JSON.stringify(filesArray));

然后我像这样发送这些数据

fetch('<?=env('app.baseURL')?>/admin/gallery', 
      method: 'POST',
      processData: false,
      headers: 
          'X-Requested-With': 'XMLHttpRequest'
      ,
      body: formData,
      data: formData,
      ).then(function (response) ...rest of the code...)

在发送此数据后,我想保存这些文件,但我想保存这些文件,但我必须先将它们分开。我正在使用 php 作为后端。

我对javascript没有太多经验,所以我可能会遗漏一些明显的东西,感谢任何帮助。

【问题讨论】:

“但我不能不先将它们分开”这是什么意思?你可以简单地用 for 循环遍历它们。 不,因为它们被保存为一个值,所以我不得不像字符串一样剪切它,我认为这不是最好的方法 您的“images[]”向 PHP 发送一个数组。你只需要使用一个循环来遍历它,如 $_FILES['images']['name'][0]、$_FILES['images']['name'][1] 等。 【参考方案1】:

在您的 for 循环中,您可以为 formData 附加使用动态名称。例如:

formData.append(`image-$i`, images[i])

或者,如果您想将图像推送到 formData 中的单个键值对,就像在您的示例中一样,您应该使用 getAll() 方法来检索图像。

formData.getAll('images[]')

【讨论】:

感谢您的帮助,似乎我认为问题有所不同,我只是在纠缠 E-telier,但在他为我提供了我应该做什么的解释后,我看到了在这里实现我想要的,你的答案正是我所需要的。谢谢你们!【参考方案2】:

这是遍历包含图像的数组的 PHP 代码:

<?php
if(isset($_FILES) && isset($_FILES['images']))
    $countfiles = count($_FILES['images']['name']);
    for($i=0;$i<$countfiles;$i++)
        $filename = $_FILES['images']['name'][$i];
        $sql = "INSERT INTO myimages (filename) VALUES ('".$filename."')";
        $db->query($sql);
        move_uploaded_file($_FILES['images']['tmp_name'][$i],'upload/'.$filename);
    

?>

【讨论】:

非常感谢您帮助我。就我而言,似乎 $_FILES 是空的。我可以确认数据通过了,就像你在评论中说的那样,它是一个数组,在使用 json_decode 之后,它很好地将所有东西重新组合在一起。不幸的是,我不能只用一组对象上传文件,至少我不知道怎么做。如果有帮助,我正在使用 CodeIgniter 4 作为 php 框架。 我不知道 CodeIgniter,我写的代码是 vanilla PHP。使用 move_uploaded_file() 将实际文件复制到服务器上。如果 $_FILES 为空,则可能是由于 CodeIgniter 使用了另一种方法。我找到了这篇关于它的文章:codeigniter.com/userguide3/libraries/file_uploading.html 这是一个来自旧版本 CodeIgniter 的库,但在当前版本中,它处理上传文件的方式与 $_FILES 相同,但处理这些文件要简单得多。现在的问题是似乎没有有效的文件,可能是因为它被检索为对象而不是文件? 文件确实需要作为表单输入文件发送。这是一个很好的解释:freecodecamp.org/news/formdata-explained/… 非常感谢,我终于搞定了,你太棒了!

以上是关于在 javascript 中的 FormData 中发送文件列表的主要内容,如果未能解决你的问题,请参考以下文章

javascript的fetch函数?

jquery使用FormData提交数据

我可以在javascript中将数组附加到“formdata”吗?

为啥 JavaScript 拦截“在野外”(在网页上)工作的 formData 不能在小提琴中工作?

使用 FormData 上传 JavaScript Blob

JavaScript:Formdata附加null值 - NumberFormatException