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

时间:2019-03-19 09:07:36

标签: javascript jquery ajax file-upload form-data

Thisthis的答案是我试图将object转换为file类型并附加到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);
  });

当我尝试同样的方法时,新创建的文件的type转换为文件后就是对象(我希望它是文件)。 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

编辑:代码笔代码

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
  });
}

1 个答案:

答案 0 :(得分:1)

  

转换前后的typeof会相同吗?

因为“文件”不是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)如何将文件对象数组发送到后端?还有其他解决方案吗?

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

您无法发送数组。您只能发送一些文本,服务器端代码可以将它们组合成一个数组。

对于两个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,
});