-
HTTP 协议是以 ASCII 码 传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。
-
协议规定 POST 提交的数据必须放在请求体中,但协议并没有规定数据必须 使用什么编码方式 。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。
-
数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 java ,以及它们的 框架如 spring mvc,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的
Content-Type
字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。
http发送方在 form表单中可以通过设置
enctype
属性来控制对表单数据的发送前的如何进行编码,
enctype
有三种,分别为:
-
application/x-www-form-urlencoded(默认),在发送前会编码所有字符,即在发送到服务器之前,所有字符都会进行编码(空格转换为 “+” 加号,”+”加号转换为空格,特殊符号转换为 ASCII HEX 值)。
-
multipart/form-data不对字符编码,用于发送二进制的文件,其他两种类型不能用于发送文件;
-
text/plain用于发送纯文本内容,空格转换为 “+” 加号,不对特殊字符进行编码,一般用于email之类的;
Post的四种传参
已PostMan里面举例
其实就是Content-Type不同
1 multipart/form-data
form表单中
enctype
属性设置为multipart/form-data
Content-Type: multipart/form-data
它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。当上传的字段是文件时,会有Content-Type来说明文件类型;content-disposition,用来说明字段的一些信息;
由于有boundary隔离,所以multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。
name=张三
age = 10086
fiel = Iterm2.md
http body内容如下:
----------------------------579457532719491135718466
Content-Disposition: form-data; name="name"
张三
----------------------------579457532719491135718466
Content-Disposition: form-data; name="no"
10086
----------------------------579457532719491135718466
Content-Disposition: form-data; name="file"; filename="Iterm2.md"
<Iterm2.md>
----------------------------579457532719491135718466--
在 spring mvc 中使用
/**
* @description: 不能加@RequestBody
*可以直接使用对象接受,也可以用@RequestParam接受
* @params: Content-Type: multipart/form-data;
* form-data可以传键值对也可以传文件
* @return:
**/
@PostMapping("formdata")
public JsonResult post1( HttpPram pram,@RequestParam("name") String name, @RequestParam("file") MultipartFile file){
final String originalFilename = file.getOriginalFilename();//文件名
System.out.println(originalFilename);
System.out.println(name);
System.out.println(pram);
return JsonResult.ok(pram);
}
2 application/x-www-form-urlencoded
form表单中
enctype
属性设置为application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded
会将表单内的数据转换为键值对,并对键值对进行URL编码 比如
name=李四&age = 23
不可以传文件
http body内容如下:
name=%E6%9D%8E%E5%9B%9B&no=10087
在 spring mvc 中使用
/**
* @description: 不能加@RequestBody
* @params: Content-Type: application/x-www-form-urlencoded
* x-www-form-urlencoded只可以传键值对不能传文件
* @return:
**/
@PostMapping("formurlencoded")
public JsonResult post2( HttpPram pram,@RequestParam("name") String name ){
System.out.println(name);
System.out.println(pram);
return JsonResult.ok(pram);
}
3 raw
可以上传任意格式的文本,可以上传text、json、xml、html等,最常用的是 json
比如Content-Type: application/json(最常用)
http body内容如下:
{
"name": "王五",
"no": "10088",
"age": 22,
"birth": "2022-10-24 00:00:00",
"chineseCalendar": "2022-10-24 00:00:00",
"height": 180
}
在 spring mvc 中使用
/**
* @description: 必须加@RequestBody
*
* @params: Content-Type: application/json
* @return:
**/
@PostMapping("json")
public JsonResult post4(@RequestBody HttpPram pram){
System.out.println(pram);
return JsonResult.ok(pram);
}
4 binary
二进制方式上传文件
Content-Type: image/png
http body内容如下:
二进制乱码,需要在 parm中传一个文件名字
在 springmvc中使用
@PostMapping("binary")
public JsonResult post4(HttpServletRequest request,String fileName,@RequestBody String src){
//System.out.println(src);//可以拿到的二进制数据
Path dest = Paths.get("你的上传目录路径"+fileName);
try {
FileCopyUtils.copy(request.getInputStream(), Files.newOutputStream(dest));
return JsonResult.ok();
}catch (Exception e){
log.error(e.getMessage());
return JsonResult.fail();
}
}
问题
1.form-data和x-www-form-urlencoded的区别?
-
form-data采用分隔符boundary隔开数据,不需要 URl编码,而且可以传文件
-
x-www-form-urlencoded采用&隔开数据,因此需要 URL编码
2.上传文件建议使用form-data
- 可以直接获取到文件名字