将对象转换为文件并通过 Ajax 发送

Convert and object to file and send via Ajax

This and this answer is my motivation for trying to convert an object to file type and append to FormData 如此:

  var fileBag = new FormData(); 
  fileArray.forEach(function(element) {        
        file_name = element.name;
        file_type = element.type;       
        var file = new File([element], file_name, {type:file_type}); 
        console.log("file type= ", typeof file);    // o/p is object
        fileBag.append(file_name, file);
  });

当我尝试相同时,新创建的文件的类型在转换为文件后是对象(我希望它是文件)。 File 对象在转换前后是一样的:

File
lastModified: 1543472205025
lastModifiedDate: Thu Nov 29 2018 11:46:45 GMT+0530 (India Standard Time) {}
name: "testFile.xlsx"
size: 1119910
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
webkitRelativePath: ""
__proto__: File

这就是我通过 Ajax

发送的方式
$.ajax({
    url: '/project/url/', 
    type: 'POST',    
    data: {'file': fileBag},
    enctype: 'multipart/form-data',
    processData: false,
    contentType: false,
    dataType: "json",
    success: function (data) { 
        console.log("data= ",data);

    },
    error: (error) => {
        console.log(JSON.stringify(error));
    }

}); 

我在 DjangoPHP 中都试过了。我得到空数组。我的问题是:

1)转换前后的typeof会不会一样?

2) 如何将文件对象数组发送到后端?还有其他解决办法吗?

这是我的codepen

编辑: Codepen 代码

var fileArray = [];
var fileBag = new FormData();

function handleFileUpload(event)
{
  var fileUploadButtonId = event.currentTarget.id;
  var files = document.getElementById(fileUploadButtonId).files;
  var fileBag = new FormData(); 
  var arrayOfAllUploadedFiles = Array.from(files);

  for(var i=0; i<arrayOfAllUploadedFiles.length; i++)
  {
    fileArray.push(arrayOfAllUploadedFiles[i]);
  }


  fileArray.forEach(function(element) {        
        file_name = element.name;
        file_type = element.type;       
        var file = new File([element], file_name, {type:file_type}); 
        console.log("file type= ", typeof file);    // o/p is object.  // o/p is object. Shouldn't this be 'file'?
        fileBag.append(file_name, file);
        alert("filebag= ",fileBag);  // this is empty
  });
}

Will the typeof before and after conversion will be the same?

因为 "file" 不是 JavaScript 数据类型。一切不是基元的都是对象。

console.log(typeof 1);
console.log(typeof "1");
console.log(typeof null);
console.log(typeof undefined);
console.log(typeof [1,2,3]);
console.log(typeof {hello: "world"});
console.log(typeof new Date());
console.log(typeof document.body);
console.log(typeof window);

2) How can I send file object arrays to backend? Is there any other solution?

  1. 了解通过 HTTP 发送数据时数据的格式
  2. 了解 jQuery
  3. 的局限性

您不能发送数组。您只能发送一些服务器端代码可以 assemble 到数组中的文本。

对于 standard encodings supported by forms,PHP 将使用其中的数据填充 $_POST

如果该数据中的字段名称以 [] 结尾,PHP 将在 $_POST 中放置一个数组。

如果你传递一个数组给jQuery ajax:

data: { someValue: [1, 2, 3] }

然后jQuery将其编码为:

someValue[]=1&someValue[]=2&someValue[]=3

…所以PHP会生成一个数组。

但是,这些值必须是 jQuery 可以理解的东西。它无法处理 FormData 个对象。

如果您想发送一个 FormData 对象(您必须这样做才能发送文件),那么您需要发送 而不是 对象:

jQuery.ajax({
    url: "/foo",
    data: a_form_data_object,
    processData: false,
    contentType: false,
});

您需要 processData,这样它就不会尝试转换 FormData 对象(也就是说,它会让 XMLHttpRequest 这样做)。您需要 contentType 来阻止它覆盖将从 FormData 对象生成的一个 XMLHttpRequest。

那么为了发送一个数组,我们回到我上面描述的规则。你说:

fileBag.append(file_name, file);

但是要获得一个数组,您需要一个以 [] 结尾的名称。

fileBag.append("myname[]", file);

最后,在你的问题中看不到,但在看你的codepen。这将为您提供一组文件:

document.getElementById(fileUploadButtonId).files;

由于它们 文件,因此使用代码将它们 转换为 文件没有任何意义。

您可以简化代码:

var fileBag = new FormData(); 
var files = document.getElementById(fileUploadButtonId).files;
var arrayOfAllUploadedFiles = Array.from(files);
fileArray.forEach(file => fileBag.append("myname[]", file);
jQuery.ajax({
    url: "/foo",
    data: fileBag,
    processData: false,
    contentType: false,
});