FormData

作者: 前端小丸子 | 来源:发表于2019-06-20 16:47 被阅读0次

    表单,FormData 对象

    表单概述

    表单用来收集用户提交的数据,发送到服务器

    <form action="/handling-page" method="post">
        <input type="text" id="name" name="name" />
        <input type="password"  name="passwd" />
        <input type="submit"  value="提交" />
    </form>
    

    表单提交

    1.<input type="submit" value="提交"> <button>提交</button>
    表单里面的<button>元素如果没有用type属性指定类型,那么默认就是submit控件。

    1. formElement.submit();
      用户点击“提交”按钮,每一个控件都会生成一个键值对,键名是控件的name属性,键值是控件的value属性。

    所有的键值对都会提交到服务器

    GET /handling-page?name=1&passwd=123&button=提交
    
    POST /handling-page HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 74
    
    name=1&passwd=123&submit_button=提交
    

    FormData 对象

    概述

    表单数据以键值对的形式向服务器发送,这个过程是浏览器自动完成的。但是有时候,我们希望通过脚本完成过程,构造和编辑表单键值对,然后通过XMLHttpRequest.send()方法发送。浏览器原生提供了 FormData 对象。

    FormData 是一个构造函数,用来生成实例。

    var formdata = new FormData(form);
    

    FormData()构造函数
    参数是一个表单元素
    省略参数,就表示一个空的表单

    我们用 FormData 对象处理上面这个表单。

    var myForm = document.getElementById('myForm');
    var formData = new FormData(myForm);
    
    // 获取某个控件的值
    formData.get('name') // ""
    
    // 设置某个控件的值
    formData.set('username', '111');
    

    实例方法

    FormData 提供以下实例方法。

    • FormData.get(key):获取指定键名对应的键值,参数为键名。如果有多个同名的键值对,则返回第一个键值对的键值。
    • FormData.getAll(key):返回一个数组,表示指定键名对应的所有键值。如果有多个同名的键值对,数组会包含所有的键值。
    • FormData.set(key, value):设置指定键名的键值,参数为键名。如果键名不存在,会添加这个键值对,否则会更新指定键名的键值。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
    • FormData.delete(key):删除一个键值对,参数为键名。
    • FormData.append(key, value):添加一个键值对。如果键名重复,则会生成两个相同键名的键值对。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
    • FormData.has(key):返回一个布尔值,表示是否具有该键名的键值对。
    • FormData.keys():返回一个遍历器对象,用于for...of循环遍历所有的键名。
    • FormData.values():返回一个遍历器对象,用于for...of循环遍历所有的键值。
    • FormData.entries():返回一个遍历器对象,用于for...of循环遍历所有的键值对。如果直接用for...of循环遍历 FormData 实例,默认就会调用这个方法。

    下面是get()getAll()set()append()方法的例子。

    var formData = new FormData();
    
    formData.set('username', '111');
    formData.append('username', '222');
    formData.get('username') // "111"
    formData.getAll('username') // ["111", "222"]
    
    formData.append('userpic[]', myFileInput.files[0], 'user1.jpg');
    formData.append('userpic[]', myFileInput.files[1], 'user2.jpg');
    

    遍历器

    var formData = new FormData();
    formData.append('key1', 'value1');
    formData.append('key2', 'value2');
    
    for (var key of formData.keys()) {
      console.log(key);
    }
    
    for (var value of formData.values()) {
      console.log(value);
    }
    
    for (var pair of formData.entries()) {
      console.log(pair[0] + ': ' + pair[1]);
    }
    

    enctype 属性 --编码类型

    决定向服务器发送数据的编码格式 , 表单能够用四种编码,

    (1)GET 方法

    如果表单使用GET方法发送数据,enctype属性无效。

    <form action="register.php"  method="get" onsubmit="AJAXSubmit()"></form>
    

    数据将以 URL 的查询字符串发出。

    (2)application/x-www-form-urlencoded

    如果表单用POST方法发送数据,并省略enctype属性,那么数据以application/x-www-form-urlencoded格式发送(因为这是默认值)。

    <form action="register.php"  method="post" onsubmit="AJAXSubmit()"></form>
    

    发送的 HTTP 请求如下。

    Content-Type: application/x-www-form-urlencoded
    
    foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
    

    (3)text/plain

    如果表单使用POST方法发送数据,enctype属性为text/plain,那么数据将以纯文本格式发送。

    <form action="register.php"  method="post" enctype="text/plain"></form>
    

    (4)multipart/form-data

    如果表单使用POST方法,enctype属性为multipart/form-data,那么数据将以混合的格式发送。

    <form action="register.php"  method="post" enctype="multipart/form-data"></form>
    

    发送的 HTTP 请求如下。

    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary6y6NbKqRG2IqmJxx
    
    ------WebKitFormBoundary6y6NbKqRG2IqmJxx
    Content-Disposition: form-data; name="filePath"
    
    sign
    ------WebKitFormBoundary6y6NbKqRG2IqmJxx
    Content-Disposition: form-data; name="bfsType"
    

    这种格式也是文件上传的格式。

    文件上传

    用户上传文件,也是通过表单。具体来说,就是通过文件输入框选择本地文件,提交表单的时候,浏览器就会把这个文件发送到服务器。

    此外,还需要将表单<form>元素的method属性设为POSTenctype属性设为multipart/form-data。其中,enctype属性决定了 HTTP 头信息的Content-Type字段的值,默认情况下这个字段的值是application/x-www-form-urlencoded,但是文件上传的时候要改成multipart/form-data

    <form method="post" enctype="multipart/form-data">
        <input type="file" id="file" name="myFile">
        <input type="submit" id="submit" name="submit_button" value="上传" />
    </form>
    

    上面的 HTML 代码中,file 控件的multiple属性,指定可以一次选择多个文件;如果没有这个属性,则一次只能选择一个文件。

    var fileSelect = document.getElementById('file');
    var files = fileSelect.files;
    

    然后,新建一个 FormData 实例对象,模拟发送到服务器的表单数据,把选中的文件添加到这个对象上面。

    var formData = new FormData();
      formData.append('photos', files[0]);
    }
    var xhr = new XMLHttpRequest();
    
    xhr.open('POST', 'handler.php', true);
    
    xhr.onload = function () {
     
    };
    xhr.send(formData);
    

    直接上传文件的情况

    var file = document.getElementById('test-input').files[0];
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'myserver/uploads');
    xhr.setRequestHeader('Content-Type', file.type);
    xhr.send(file);
    

    Content-Type

    Content-Type(MediaType),即是Internet Media Type,互联网媒体类型,也叫做MIME类型。在互联网中有成百上千中不同的数据类型,HTTP在传输数据对象时会为他们打上称为MIME的数据格式标签,用于区分数据类型。最初MIME是用于电子邮件系统的,后来HTTP也采用了这一方案。
    在HTTP协议消息头中,使用Content-Type来表示请求和响应中的媒体类型信息。它用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析并展示html等等。

    Content-Type:type/subtype ;parameter

    type:主类型,任意的字符串,如text,如果是号代表所有;
    subtype:子类型,任意的字符串,如html,如果是
    号代表所有,用“/”与主类型隔开;
    parameter:可选参数,如charset,boundary等。

    Content-Type: text/html;
    Content-Type: application/json;charset:utf-8;
    

    application/x-www-form-urlencoded

    HTTP会将请求参数用key1=val1&key2=val2的方式进行组织,并放到请求实体里面,注意如果是中文或特殊字符会自动进行URL转码。不支持文件,一般用于表单提交。

    multipart/form-data

    这是一个多部分多媒体类型。首先生成了一个 boundary 用于分割不同的字段,在请求实体里每个参数以------boundary开始,然后是附加信息和参数名,然后是空行,最后是参数内容。多个参数将会有多个boundary块。如果参数是文件会有特别的文件域。最后以------boundary–为结束标识。multipart/form-data支持文件上传的格式,一般需要上传文件的表单则用该类型。


    20190111175221876.png

    application/json

    application/xml

    Content-Type的使用

    request 的Content-Type

    一般我们在开发的过程中需要注意客户端发送请求(Request)时的Content-Type设置,特别是使用ajax的时候,如果设置得不准确,很有可能导致请求失败。比如在spring中,如果接口使用了@RequestBody,spring强大的自动解析功能,会将请求实体的内容自动转换为Bean,但前提是请求的Content-Type必须设置为application/json,否正就会返回415错误。

    response的Content-Type

    服务端响应(Response)的Content-Type最好也保持准确,虽然一般web开发中,前端解析响应的数据不会根据Content-Type,并且服务端一般能自动设置准确的Content-Type,但是如果乱设置某些情况下可能会有问题,比如导出文件,打开图片等。

    相关文章

      网友评论

          本文标题:FormData

          本文链接:https://www.haomeiwen.com/subject/nqujqctx.html