https://www.jianshu.com/p/e984c3619019
FormData的主要用途有两个:
1、将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
2、异步上传文件
一、创建formData对象
1、创建一个空对象:
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//可以通过append()方法来追加数据
formdata.append("name","laotie");
//通过get方法对值进行读取
console.log(formdata.get("name"));//laotie
//通过set方法对值进行设置
formdata.set("name","laoliu");
console.log(formdata.get("name"));//laoliu
2、通过表单对formData进行初始化
创建表单:
<form id="advForm">
<p>广告名称:<input type="text" name="advName" value="xixi"></p>
<p>广告类别:<select name="advType">
<option value="1">轮播图</option>
<option value="2">轮播图底部广告</option>
<option value="3">热门回收广告</option>
<option value="4">优品精选广告</option>
</select></p>
<p><input type="button" id="btn" value="添加"></p>
</form>
通过表单元素作为参数,实现对formData的初始化:
//获得表单按钮元素
var btn=document.querySelector("#btn");
//为按钮添加点击事件
btn.onclick=function(){
//根据ID获得页面当中的form表单元素
var form=document.querySelector("#advForm");
//将获得的表单元素作为参数,对formData进行初始化 (DOM对象作为new FormDate()的参数)
var formdata=new FormData(form);
//通过get方法获得name为advName元素的value值
console.log(formdata.get("advName"));//xixi
//通过get方法获得name为advType元素的value值
console.log(formdata.get("advType"));//1
}
二、操作方法
1、通过get(key)与getAll(key)来获取相对应的值
// 获取key为age的第一个值
formdata.get("age");
// 获取key为age的所有值,返回值为数组类型
formdata.getAll("age");
2、通过append(key,value)在数据末尾追加数据
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
//通过append()方法在末尾追加key为name值为laoli的数据
formdata.append("name","laoli");
//通过append()方法在末尾追加key为name值为laotie的数据
formdata.append("name","laotie");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoliu
//通过getAll方法读取key为name的所有值
console.log(formdata.getAll("name"));//["laoliu", "laoli", "laotie"]
3、通过set(key, value)来设置修改数据
key的值不存在,会添加一条数据
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//如果key的值不存在会为数据添加一个key为name值为laoliu的数据
formdata.set("name","laoli");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoli
key的值存在,会修改对应的value值
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
//通过append()方法在末尾追加key为name值为laoliu2的数据
formdata.append("name","laoliu2");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoliu
//通过getAll方法读取key为name的所有值
console.log(formdata.getAll("name"));//["laoliu", "laoliu2"]
//将存在的key为name的值修改为laoli
formdata.set("name","laoli");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoli
//通过getAll方法读取key为name的所有值
console.log(formdata.getAll("name"));//["laoli"]
4、通过has(key)来判断是否存在对应的key值
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
//判断是否包含key为name的数据
console.log(formdata.has("name"));//true
//判断是否包含key为age的数据
console.log(formdata.has("age"));//false
5、通过delete(key)可以删除数据
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
console.log(formdata.get("name"));//laoliu
//删除key为name的值
formdata.delete("name");
console.log(formdata.get("name"));//null
三、通过XMLHttpRequest发送数据
创建表单:
<form id="advForm">
<p>广告名称:<input type="text" name="advName" value="xixi"></p>
<p>广告类别:<select name="advType">
<option value="1">轮播图</option>
<option value="2">轮播图底部广告</option>
<option value="3">热门回收广告</option>
<option value="4">优品精选广告</option>
</select></p>
<p>广告图片:<input type="file" name="advPic"></p>
<p>广告地址:<input type="text" name="advUrl"></p>
<p>广告排序:<input type="text" name="orderBy"></p>
<p><input type="button" id="btn" value="添加"></p>
</form>
发送数据:
var btn=document.querySelector("#btn");
btn.onclick=function(){
var formdata=new FormData(document.getElementById("advForm"));
var xhr=new XMLHttpRequest();
xhr.open("post","http://127.0.0.1/adv");
xhr.send(formdata);
xhr.onload=function(){
if(xhr.status==200){
//...
}
}
}
=======================
原文链接:https://blog.csdn.net/hsl0530hsl/article/details/88558353
XMLHttpRequest.send()方法用于实际发出 HTTP 请求。它的参数是可选的,如果不带参数,就表示 HTTP 请求只有一个 URL,没有数据体,典型例子就是 GET 请求;如果带有参数,就表示除了头信息,还带有包含具体数据的信息体,典型例子就是 POST 请求。
下面是 GET 请求的例子。
var xhr = new XMLHttpRequest();
xhr.open('GET',
'http://www.example.com/?id=' + encodeURIComponent(id),
true
);
xhr.send(null);
上面代码中,GET请求的参数,作为查询字符串附加在 URL 后面。
下面是发送 POST 请求的例子。
var xhr = new XMLHttpRequest();
var data = 'email='
+ encodeURIComponent(email)
+ '&password='
+ encodeURIComponent(password);
xhr.open('POST', 'http://www.example.com', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(data);
注意,所有 XMLHttpRequest 的监听事件,都必须在send()方法调用之前设定。
send方法的参数就是发送的数据。多种格式的数据,都可以作为它的参数。
void send();
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(String data);
void send(FormData data);
如果send()发送 DOM 对象,在发送之前,数据会先被串行化。如果发送二进制数据,最好是发送ArrayBufferView或Blob对象,这使得通过 Ajax 上传文件成为可能。
下面是发送表单数据的例子。FormData对象可以用于构造表单数据。
var formData = new FormData();
formData.append('username', '张三');
formData.append('email', 'zhangsan@example.com');
formData.append('birthDate', 1940);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/register');
xhr.send(formData);
上面代码中,FormData对象构造了表单数据,然后使用send()方法发送。它的效果与发送下面的表单数据是一样的。
<form id='registration' name='registration' action='/register'>
<input type='text' name='username' value='张三'>
<input type='email' name='email' value='zhangsan@example.com'>
<input type='number' name='birthDate' value='1940'>
<input type='submit' onclick='return sendForm(this.form);'>
</form>
下面的例子是使用FormData对象加工表单数据,然后再发送。
function sendForm(form) {
var formData = new FormData(form);
formData.append('csrf', 'e69a18d7db1286040586e6da1950128c');
var xhr = new XMLHttpRequest();
xhr.open('POST', form.action, true);
xhr.onload = function() {
// ...
};
xhr.send(formData);
return false;
}
var form = document.querySelector('#registration');
sendForm(form);
============================
常见的content-type讲解
(1)application/x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
首先,Content-Type 被指定为 application/x-www-form-urlencoded;
其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。例如 PHP 中,_POST[‘title’] 可以获取到 title 的值,POST[‘title’]可以获取到title的值,_POST[‘sub’] 可以得到 sub 数组。
很多时候,我们用 Ajax 提交数据时,也是使用这种方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默认值都是「application/x-www-form-urlencoded;charset=utf-8」。
(2)multipart/form-data
这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 form 的 enctyped 等于这个值。
客户端form标签:
<form action="url" enctype="multipart/form-data" method="post"></form>
直接来看一个生成的请求示例:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。
然后 Content-Type 里指明了数据是以 mutipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 –boundary 开始,紧接着内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 –boundary– 标示结束。关于 mutipart/form-data 的详细定义,请前往 rfc1867 查看。
这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。
上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段原生 form 表单也只支持这两种方式。但是随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。
(3)application/json
application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。
Google 的 AngularJS 中的 Ajax 功能,默认就是提交 JSON 字符串。例如下面这段代码:
var data = {'title':'test', 'sub' : [1,2,3]};
$http.post(url, data).success(function(result) {
...
});
最终发送的请求是:
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title":"test","sub":[1,2,3]}
这种方案,可以方便的提交复杂的结构化数据,特别适合 RESTful 的接口。各大抓包工具如 Chrome 自带的开发者工具、Firebug、Fiddler,都会以树形结构展示 JSON 数据,非常友好。但也有些服务端语言还没有支持这种方式,例如 php 就无法通过 $_POST 对象从上面的请求中获得内容。这时候,需要自己动手处理下:在请求头中 Content-Type 为 application/json 时,从 php://input 里获得原始输入流,再 json_decode 成对象。一些 php 框架已经开始这么做了。
(4)text/xml
它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。典型的 XML-RPC 请求是这样的:
POST http://www.example.com HTTP/1.1
Content-Type: text/xml
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
XML-RPC 协议简单、功能够用,各种语言的实现都有。它的使用也很广泛,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服务等等。JavaScript 中,也有现成的库支持以这种方式进行数据交互,能很好的支持已有的 XML-RPC 服务。不过,我个人觉得 XML 结构还是过于臃肿,一般场景用 JSON 会更灵活方便。
=======================
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/send
XMLHttpRequest.send()
XMLHttpRequest.send()
方法用于发送 HTTP 请求。如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回。XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。
如果没有使用 setRequestHeader()
方法设置 Accept
头部信息,则会发送带有 "* / *"
的Accept
头部。
Note: 请注意不要使用一个简单的AarryBuffer对象作为参数,ArrayBuffer已经不再是ajax规范的一部分,请改用ArrayBufferView(有关信息请参考兼容性列表。)
语法
<span style="color:#212121">XMLHttpRequest.send(body)</span>
参数
body
可选
- 可以为
Document
, 在这种情况下,它在发送之前被序列化. - 为
XMLHttpRequestBodyInit
, 从 per the Fetch spec (规范中)可以是Blob
,BufferSource
(en-US),FormData
,URLSearchParams
, 或者USVString
对象. null
null
.
返回值
undefined
.
例外
Exception | Description |
---|---|
InvalidStateError | send() has already been invoked for the request, and/or the request is complete. |
NetworkError | The resource type to be fetched is a Blob, and the method is not GET . |
<span style="color:#212121">XMLHttpRequest.send();
XMLHttpRequest.send(ArrayBuffer data);
XMLHttpRequest.send(ArrayBufferView data);
XMLHttpRequest.send(Blob data);
XMLHttpRequest.send(Document data);
XMLHttpRequest.send(DOMString? data);
XMLHttpRequest.send(FormData data);
</span>
如果发送的数据是Document对象,需要在发送之前将其序列化。当发送一个Document对象时,Firefox 3之前的版本都是使用utf-8编码发送请求的;FireFox 3则使用由body.xmlEncoding
指定的编码格式正确的发送文档,但如果未指定编码格式,则使用utf-8编码格式发送。
如果是一个nsIInputStream接口,它必须与nsIUploadChannel的setUploadStream()方法兼容。在这种情况下,将 Content-Length的头部添加到请求中,它的值则使用nsIInputStream接口的available()方法获取。任何报头包括在数据流顶部的都会被当做报文主体。所以,应该在发送请求即调用send()方法之前使用setRequestHeader()
方法设置 Content-Type头部来指定数据流的MIME类型。
发送二进制内容的最佳方法(如上传文件)是使用一个与send()方法结合的 ArrayBufferView 或者Blobs
案例: GET
<span style="color:#212121"><code>var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
xhr.onload = function () {
// 请求结束后,在此处写处理代码
};
xhr.send(null);
// xhr.send('string');
</code>// <code>xhr.send(new Blob());
// xhr.send(new Int8Array());
// xhr.send({ form: 'data' });
// xhr.send(document);</code>
</span>
案例: POST
<span style="color:#212121"><code>var xhr = new XMLHttpRequest();
xhr.open("POST", '/server', true);
//发送合适的请求头信息
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onload = function () {
// 请求结束后,在此处写处理代码
};
xhr.send("foo=bar&lorem=ipsum");
// xhr.send('string');
</code>// <code>xhr.send(new Blob());
// xhr.send(new Int8Array());
// xhr.send({ form: 'data' });
// xhr.send(document);</code></span>
========================
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
XMLHttpRequest
XMLHttpRequest
(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest
在 AJAX 编程中被大量使用。
尽管名称如此,XMLHttpRequest
可以用于获取任何类型的数据,而不仅仅是 XML。它甚至支持 HTTP 以外的协议(包括 file:// 和 FTP),尽管可能受到更多出于安全等原因的限制。
如果您的通信流程需要从服务器端接收事件或消息数据,请考虑通过 EventSource
接口使用 server-sent events。对于全双工的通信, WebSocket 可能是更好的选择。
构造函数
该构造函数用于初始化一个 XMLHttpRequest
实例对象。在调用下列任何其他方法之前,必须先调用该构造函数,或通过其他方式,得到一个实例对象。
属性
此接口继承了 XMLHttpRequestEventTarget
和 EventTarget
的属性。
XMLHttpRequest.onreadystatechange
当 readyState
属性发生变化时,调用的 EventHandler
(en-US)。
返回 一个无符号短整型(unsigned short
)数字,代表请求的状态码。
返回一个 ArrayBuffer
、Blob
、Document
,或 DOMString
,具体是哪种类型取决于 XMLHttpRequest.responseType
的值。其中包含整个响应实体(response entity body)。
XMLHttpRequest.responseText
只读
返回一个 DOMString
,该 DOMString
包含对请求的响应,如果请求未成功或尚未发送,则返回 null
。
一个用于定义响应类型的枚举值(enumerated value)。
返回经过序列化(serialized)的响应 URL,如果该 URL 为空,则返回空字符串。
返回一个 Document
,其中包含该请求的响应,如果请求未成功、尚未发送或时不能被解析为 XML 或 HTML,则返回 null
。
返回一个无符号短整型(unsigned short
)数字,代表请求的响应状态。
返回一个 DOMString
,其中包含 HTTP 服务器返回的响应状态。与 XMLHTTPRequest.status
不同的是,它包含完整的响应状态文本(例如,"200 OK
")。
注意:根据 HTTP/2 规范(8.1.2.4 Response Pseudo-Header Fields,响应伪标头字段),HTTP/2 没有定义任何用于携带 HTTP/1.1 状态行中包含的版本(version)或者原因短语(reason phrase)的方法。
一个无符号长整型(unsigned long
)数字,表示该请求的最大请求时间(毫秒),若超出该时间,请求会自动终止。
XMLHttpRequestEventTarget.ontimeout
当请求超时调用的 EventHandler
(en-US)。
XMLHttpRequestUpload
,代表上传进度。
XMLHttpRequest.withCredentials
一个布尔值
(en-US),用来指定跨域 Access-Control
请求是否应当带有授权信息,如 cookie 或授权 header 头。
非标准属性
一个 nsIChannel
,对象在执行请求时使用的通道。
一个布尔值,如果为真,请求将在没有 cookie 和身份验证 header 头的情况下发送。
一个布尔值,如果为真,则在请求时不会强制执行同源策略。
XMLHttpRequest.mozBackgroundRequest
一个布尔值,它指示对象是否是后台服务器端的请求。
XMLHttpRequest.mozResponseArrayBuffer
已废弃 Gecko 6 只读
一个 ArrayBuffer
,把请求的响应作为一个 JavaScript TypedArray。
XMLHttpRequest.multipart
(en-US)已废弃 Gecko 22
这是一个 Gecko 专有属性,是一个布尔值,已在 Firefox/Gecko 22 中被删除。请考虑使用 Server-Sent Event、Web Socket、或来自进度事件的 responseText
代替。
事件处理器
作为 XMLHttpRequest
实例的属性之一,所有浏览器都支持 onreadystatechange
。
后来,许多浏览器实现了一些额外的事件(onload
、onerror
、onprogress
等)。详见Using XMLHttpRequest。
更多现代浏览器,包括 Firefox,除了可以设置 on*
属性外,也提供标准的监听器 addEventListener()
API 来监听XMLHttpRequest
事件。
方法
如果请求已被发出,则立刻中止请求。
XMLHttpRequest.getAllResponseHeaders()
以字符串的形式返回所有用 CRLF 分隔的响应头,如果没有收到响应,则返回 null
。
XMLHttpRequest.getResponseHeader()
返回包含指定响应头的字符串,如果响应尚未收到或响应中不存在该报头,则返回 null
。
初始化一个请求。该方法只能在 JavaScript 代码中使用,若要在 native code 中初始化请求,请使用 openRequest()
。
XMLHttpRequest.overrideMimeType()
覆写由服务器返回的 MIME 类型。
发送请求。如果请求是异步的(默认),那么该方法将在请求发送后立即返回。
XMLHttpRequest.setRequestHeader()
设置 HTTP 请求头的值。必须在 open()
之后、send()
之前调用 setRequestHeader()
方法。
非标准方法
XMLHttpRequest.init()
在 C++ 代码中初始化一个 XHR 对象。
警告:该方法不能在 JavaScript 代码中使用。
初始化一个请求。这个方法只能在原生 C++ 代码中使用;如果用 JavaScript 代码来初始化请求,使用 open()
代替。可参考 open()
的文档。
XMLHttpRequest.sendAsBinary()
send()
方法的变体,用来发送二进制数据。
事件
当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort()
时。
也可以使用 onabort
属性。
当 request 遭遇错误时触发。
也可以使用 onerror
属性
XMLHttpRequest
请求成功完成时触发。
也可以使用 onload
属性.
当请求结束时触发, 无论请求成功 ( load
) 还是失败 (abort
或 error
)。
也可以使用 onloadend
属性。
接收到响应数据时触发。
也可以使用 onloadstart
属性。
当请求接收到更多数据时,周期性地触发。
也可以使用 onprogress
属性。
在预设时间内没有接收到响应时触发。
也可以使用 ontimeout
属性。