Content-Type是指http/https发送信息至服务器时的内容编码类型,Content-Type用于表明发送数据流的类型,服务器根据编码类型使用特定的解析方式,获取数据流中的数据。

在网络请求中,常用的Content-Type有如下:

  • text/html,如果Content-Type的值是text/html,那么接下来就是浏览器的解析和渲染工作了
  • text/plain
  • text/css
  • text/javascript
  • image/jpeg
  • image/png
  • image/gif

以上几种都是常见的页面资源类型。

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • application/xml

以上几种是ajax的请求,表单提交或上传文件的常用的资源类型。

1. application/x-www-form-urlencoded

原生**Form**表单默认的提交方式,支持GET/POST等方法,所有数据被格式化成键值对key1=value1&key2=value2 形式的字符串(特殊字符需要转义成utf-8编码,如/会变成%2F)。

首先来看下form表单中POST默认提交方式的数据,代码如下:

  1. <form action="http://www.example.com" method="POST">
  2. <p>username: <input type="text" name="fname" /></p>
  3. <p>age: <input type="text" name="age" /></p>
  4. <input type="submit" value="提交" />
  5. </form>

请求信息如下:

image.png

GET请求的话,格式化的字符串将直接拼接在url后发送到服务端;POST请求的话,格式化的字符串将放在请求体的Form Data中发送,但是在chromenetwork面板下,form形式的请求体是被解析的,展示成formData的形式。

再来看下使用jQueryajax方法提交的数据,代码如下:

  1. var obj = {
  2. "name": 'CntChen',
  3. "info": 'Front-End',
  4. };
  5. $('.btn').click(function() {
  6. $.ajax({
  7. url: 'www.example.com',
  8. type: 'POST',
  9. dataType: 'json',
  10. data: obj,
  11. success: function(d) {}
  12. })
  13. });

请求信息如下:

image.png

可以看出,使用jQuerypost请求默认的Content-Typeapplication/x-www-form-urlencoded

控制台中访问不到formData的数据,在控制台看到的是FormData原型,存储的数据没有以对象属性的方式体现,可以理解为类的私有字段,外界访问不到,但是可以通过formData.get("name")的方式获取到对应的表单数据。

2. multipart/form-data

使用表单上传文件时,必须指定表单的enctype属性值为multipart/form-data。 请求体被分割成多部分,每部分使用--boundary分割。

代码如下:

  1. <form action="http://www.example.com" method="POST" enctype="multipart/form-data">
  2. <input type="file" id="imageInput" name="file" />
  3. </form>

请求信息如下:

image.png

3. application/json

http请求中,Content-Type的默认值都为application/x-www-form-urlencoded, 这种编码格式的特点是:name/value键值对,每组之间使用&连接,而namevalue之间是使用=连接,比如key=SHEN&name=111&password=123456。键值对一般的情况下是没有什么问题的,是很简单的json形式,比如如下:

  1. {
  2. "name": 111,
  3. "password": 123456
  4. }

它会解析成name=111&password=123456这样的形式。但是在一些复杂的情况下,比如需要传一个复杂的json对象,也就是对象嵌套数组的情况下,比如如下代码:

  1. {
  2. obj: [
  3. {
  4. "name": 111,
  5. "password": 123456
  6. }
  7. ]
  8. }

如果将这样复杂的对象,以**application/x-www-form-urlencoded**形式传递的话,会被解析成**obj[0]['name']=111&obj[0].['password']=123456**这样的形式。然后再转成json形式:

  1. {
  2. "obj": [
  3. {
  4. "name": 111,
  5. "password": 123456
  6. }
  7. ]
  8. }

对于一些复杂的数据对象,比如对象里面再嵌套数组的话,建议使用application/json传递比较好,后台那边也会要求使用application/json。因为后台那边不使用application/json,而使用默认的application/x-www-form-urlencoded传递的话,还要额外的多一步将参数再解析成json对象,如果是更复杂的json对象,那么后台的工作量将更大,所以直接json对象传递的话,对于后台来说更简单。

通过json的形式将数据发送给服务器。json的形式的优点是它可以传递结构复杂的数据形式,比如对象里面嵌套数组这样的形式等。

代码如下:

  1. $('.btn').click(function() {
  2. $.ajax({
  3. url: 'http://www.example.com',
  4. type: 'POST',
  5. dataType: 'json',
  6. contentType: 'application/json',
  7. data: JSON.stringify({a: [{b:1, a:1}]}),
  8. success: function(res) {}
  9. })
  10. });

但是如上代码,在浏览器运行后,发现跨域了,我们看如下截图所示:

image.png

image.png

3.1 理解 ajax 跨域设置 Content-Type:application/json

在使用**ajax**跨域请求时,如果设置**Header****Content-Type****application/json**,它会发两次请求。第一次先发**Method****OPTIONS**的请求到服务器,这个请求会询问服务器支持那些请求方法(比如**GET****POST**)等。如果这个请求支持跨域的话,就会发送第二个请求,否则的话在控制台会报错,第二个请求不会请求。

OPTIONS请求的返回图如下:

image.png

图中箭头指向的Allow就是服务器返回的支持的方法。不仅如此,如果想要用**application/json**发送跨域请求,服务器端还必须设置一个名为**Access-Control-Allow-Headers****Header**,将它的值设置为**Content-Type**,表明服务器能够接收到前端发送的请求中的**Content-Type**属性并使用它的值。否则第二次请求也是发不出去的,浏览器console会报错,并提示你服务器没有设置Access-Control-Allow-Headers

java代码如下:

  1. httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
  2. httpResponse.setHeader("Access-Control-Allow-Methods", "POST");
  3. httpResponse.setStatus(200);
  4. httpResponse.setContentType("application/json");

所以简单做个demo,不跨域的如下:

  1. $('.btn').click(function() {
  2. $.ajax({
  3. url: 'http://localhost:8081/api.json',
  4. type: 'POST',
  5. dataType: 'json',
  6. contentType: 'application/json',
  7. data: JSON.stringify({a: [{b:1, a:1}]}),
  8. success: function(res) {}
  9. })
  10. });

请求信息如下:

image.png

如上可以看到json格式提交的数据会显示Request Payload