HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。 其中 POST 一般用来向服务端提交数据,具体到项目中,前后端交互时必须首先约定编码方式,本文主要讨论 POST 提交数据的几种编码方式。
POST请求的编码方式
HTTP协议规定 POST 提交的数据必须放在消息主体(body)中,但协议并没有规定数据必须使用什么编码方式。 服务端通常是根据请求头headers中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对body进行解析。 所以用post方法提交数据,必须指定Content-Type头,如果不指定,浏览器会添加默认的Content-Type头。
目前常见的 POST 提交数据方式见下
1. application/x-www-form-urlencoded
form表单提交,自动添加Content-Type头
html中的form标签可以实现表单提交数据,form的enctype属性用于设置编码方式,默认值为application/x-www-form-urlencoded,发送请求时Content-Type头为application/x-www-form-urlencoded
编码方式为 application/x-www-form-urlencoded时,数据在发送到服务器之前,会将表单内的数据转换为键值对(所有的字段都被作为字符串处理),字段形式为fieldname=value,用&分隔每个字段。比如,username=admin&password=123456,并将所有字符都会进行URL 转码。 在线URL编码解码:http://tool.chinaz.com/tools/urlencode.aspx
form的enctype属性值
值描述application/x-www-form-urlencoded在发送前编码所有字符(默认)multipart/form-data不对字符编码,在使用包含文件上传控件的表单时,必须使用该值。text/plain空格转换为 “+” 加号,但不对特殊字符编码。
Ajax 提交数据,手动设置Content-type
var xhr=new XMLHttpRequest();
xhr.open("POST","https://www.fastmock.site/mock/d6b39fde63cbe98a4f2fb92ff5b25a6d/api/add",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
2、multipart/form-data
编码方式为 multipart/form-data时需要首先在HTTP请求头设置一个分隔符,即:boundary的属性值,然后,将每个字段用分隔符分隔,最后一个分隔符表示结束。 数据将被编码为一条消息,由于存在分隔符,既可以上传键值对,也可以上传文件,通常用于上传二进制的文件。
form表单提交
如果使用表单上传文件,需要将表单的enctype设置为multipart/form-data
可以在js中创建一个FormData对象提交数据,使用 FormData对象,浏览器会自动识别并添加请求头 Content-Type: multipart/form-data 下面是一个带预览功能的上传图片的例子:
window.onload=function () {
var btn=document.getElementById("btn");
var file = document.getElementById('thumbnail');
var img = document.getElementById('img');
//图片预览
file.addEventListener('change',function (event) {
var uploadFile = event.target.files[0]
if (uploadFile) {
var reader = new FileReader();// 创建流对象
reader.readAsDataURL(uploadFile)
}
reader.onload = function(e) {
img.src = e.target.result
}
})
//图片上传
btn.addEventListener('click',function () {
var formData = new FormData();
formData.append("caption", "缩略图");
formData.append('thumbnail', file.files[0]);
var xhr= new XMLHttpRequest();
xhr.open("POST", "http://localhost:5000/api/upload");
xhr.send(formData);
})
}
3、application/json
目前常用的Content-Type类型,用来告诉服务端消息主体是序列化后的 JSON 字符串。一些前端框架中post请求默认采用这种编码方式。前端无法将表单的enctype属性指定为application/json,通常使用ajax的方式发送这种编码形式的请求。
var xhr= new XMLHttpRequest();
xhr.open("POST","/api/",true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({"login_name": "test", "login_password": "123456"}));
ajax发送上述三种编码格式的区别
var xhr1 = new XMLHttpRequest();
xhr1.open("POST", "http://localhost:5000/api/users/login", true);
xhr1.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr1.send("login_name=test&login_password=123456");
var xhr2 = new XMLHttpRequest();
var formData = new FormData();
formData.append("login_name", "test");
formData.append("login_password", "123456");
xhr2.open("POST", "http://localhost:5000/api/users/login", true);
xhr2.send(formData);
var xhr3 = new XMLHttpRequest();
xhr3.open("POST", "http://localhost:5000/api/users/login", true);
xhr3.setRequestHeader("Content-Type", "application/json");
xhr3.send(JSON.stringify({"login_name": "test", "login_password": "123456"}));