使用 XMLHttpRequest(二):编码请求主体
表单编码的请求
表单数据编码格式有一个正式的 MIME 类型:
application/x-www-form-urlencoded
因此,提交表单时会自动对表单数据进行编码。一个简单的表单编码字符串如下:
find=pizza&zipcode=02134&radius=1km
但是通过 XMLHttpRequest 对象发送请求时,发送给服务器的可能是一个 JavaScript 对象,需要我们手动对其进行编码:
// 发送 POST 请求
function postData(url, data, callback) {
var request = new XMLHttpRequest();
request.open("POST", url);
request.onreadystatechange = function () {
if (request.readyState === 4) {
callback(request);
}
};
request.setRequestHeader("Content-Type", "application/x-www-form-encoded");
request.send(encodeFormData(data));
}
// 发送 GET 请求
function getData(url, data, callback) {
var request = new XMLHttpRequest();
request.open("GET", url + "?" + encodeFormData(data));
request.onreadystatechange = function () {
if (request.readyState === 4 && callback) {
callback(request);
}
};
request.send(null);
}
// 对数据进行编码
function encodeFormData(data) {
if (!data)
return "";
var pairs = [];
for (var name in data) {
if (!data.hasOwnProperty(name))
continue;
if (typeof data[name] === "function")
continue;
var value = data[name].toString();
name = encodeURIComponent(name.replace("%20", "+"));
value = encodeURIComponent(value.replace("%20", "+"));
pairs.push(name + "=" + value);
}
return pairs.join("&");
}
JSON 编码的请求
function postJSON(url, data, callback) {
var request = new XMLHttpRequest();
request.open("POST", url);
request.onreadystatechange = function () {
if (request.readyState === 4 && callback)
callback(request);
};
request.setRequestHeader("Content-Type", "application/json");
request.send(JSON.stringify(data));
}
XML 编码的请求
function postQuery(url, what, where, radius, callback) {
var request = new XMLHttpRequest();
request.open("POST", url);
request.onreadystatechange = function () {
if (request.readyState === 4 && callback)
callback(request);
};
// 创建一个XML文档
var doc = document.implementation.createDocument("", "query", null);
var query = doc.documentElement;
var find = doc.createElement("find");
query.appendChild(find);
find.setAttribute("zipcode", where);
find.setAttribute("radius", radius);
find.appendChild(doc.createTextNode(what));
request.send(doc); // 此时 Content-Type 头会自动设置
}
上传文件
XHR2 API 允许通过向 send()
方法传入 File 对象来实现文件上传:
whenReady(function () {
var elts = document.getElementsByTagName("input");
for (var i = 0; i < elts.length; i++) {
var input = elts[i];
if (input.type !== "file")
continue;
var url = input.getAttribute("data-uploadto");
if (!url) {
continue;
}
input.addEventListener("change", function () {
var file = this.files[0];
if (!file)
return;
var xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(file);
}, false);
}
});
multipart/form-data 请求
当 HTML 表单同时包含文件上传元素和其他元素时,浏览器不能使用普通的表单编码而必须使用 multipart/form-data
这种特殊的 Content-Type 来提交表单。
XHR2 API 中定义了新的 FormData API,通过它可以很容易实现多部分请求主体:
function postFormData(url, data, callback) {
if (typeof FormData === "undefined")
throw new Error("FormData is not implemented");
var request = new XMLHttpRequest();
request.open("POST", url);
request.onreadystatechange = function () {
if (request.readyState === 4 && callback)
callback(request);
};
var formdata = new FormData();
for (var name in data) {
if (!data.hasOwnProperty(name))
continue;
var value = data[name];
if (typeof value === "function")
continue;
formdata.append(name, value);
}
request.send(formdata); // 自动设置 Content-Type 为 multipart/form-data
}
无评论