formdata详解

Posted by Cycle263 on September 22, 2017

formdata

XMLHttpRequest Level 2添加了一个新的接口FormData。利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件, 我们还可以使用XMLHttpRequest的send()方法来异步的提交这个”表单”。比起普通的ajax, 使用FormData的最大优点就是我们可以异步上传一个二进制文件.

  • FormData对象会自动将form中的表单值也包含进去,包括文件内容也会被编码之后包含进去。将文件内容自动序列化成字符串(相当于readAsBinaryString的手动拼接字符串)

  • 如果要处理文件的二进制流,则需要调用ArrayBuffer来处理二进制,完了再倒腾成Blob,再倒腾成FormData。

  • 通过xhr发送数据

    var formData = new FormData();
    formData.append("username", "Groucho");
    formData.append("accountnum", 123456); //数字123456会被立即转换成字符串 "123456"
    
    // HTML 文件类型input,由用户选择
    formData.append("userfile", fileInputElement.files[0]), 'fileName';
    
    // JavaScript file-like 对象
    var content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的正文...
    var blob = new Blob([content], { type: "text/xml"});
    
    formData.append("webmasterfile", blob, 'filename');
    
    var request = new XMLHttpRequest();
    request.open("POST", "http://foo.com/submitform.php");
    request.send(formData);
    
    // jQuery 处理FormData
    var fd = new FormData(document.querySelector("form"));
    fd.append("CustomField", "This is some extra data");
    $.ajax({
      url: "stash.php",
      type: "POST",
      data: fd,
      processData: false,  // 不处理数据
      contentType: false   // 不设置内容类型
    });
    

FormData 操作方法

  • get

    通过get(key)/getAll(key)来获取对应的value

    formData.get("name"); // 获取key为name的第一个值 formData.getAll("name"); // 返回一个数组,获取key为name的所有值

  • append

    通过append(key, value[, fileName])来添加数据,如果指定的key不存在则会新增一条数据,如果key存在,则添加到数据的末尾。参数fileName(可选),指定文件的文件名, 当value参数被指定为一个Blob对象或者一个File对象时, 该文件名会被发送到服务器上, 对于Blob对象来说, 这个值默认为”blob”.

    formData.append("k1", "v1");
    formData.append("k1", "v2");
    formData.append("k1", "v1");
    
    formData.get("k1"); // "v1"
    formData.getAll("k1"); // ["v1","v2","v1"]
    
  • set

    通过set(key, value)来设置修改数据,如果指定的key不存在则会新增一条,如果存在,则会修改对应的value值。

    formData.append("k1", "v1");
    formData.set("k1", "1");
    formData.getAll("k1"); // ["1"]
    
  • has

    通过has(key)来判断是否对应的key值

  • delete

    通过delete(key),来删除数据,key也会被删除,has方法判断为false

  • entries / values / keys

    通过entries()来获取一个迭代器,然后遍历所有的数据.

    formData.append("k1", "v1");
    formData.append("k1", "v2");
    formData.append("k2", "v1");
    
    var i = formData.entries();
    
    i.next(); // {done:false, value:["k1", "v1"]}
    i.next(); // {done:false, value:["k1", "v2"]}
    i.next(); // {done:false, value:["k2", "v1"]}
    i.next(); // {done:true, value:undefined}
    
    var j = formData.values();
    
    console.log(j.next()); // {done:false, value: "v1"}
    console.log(j.next()); // {done:false, value: "v2"}
    console.log(j.next()); // {done:false, value: "v1"}
    console.log(j.next()); // {done:true, value:undefined}
    

vs octet-stream vs x-www-form-urlencoded

  • Content-Type

    Content-Type: application/x-www-form-urlencoded

    Content-Type: multipart/form-data; boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC

    Content-Type: application/octet-stream

  • 提交内容

    formdata可以提交普通键值对,也可以提交(多个)文件键值对。octet-stream 只能提交二进制,而且只能提交一个二进制;如果提交文件,只能提交一个文件, 后台接收参数只能有一个,而且只能是流(或者字节数组)。x-www-form-urlencoded提交的是键值对,所有键与值都会被urlencoded,但不能提交二进制。