在常见业务开发中,POST请求常常在这些地方使用:前端表单提交时、调用接口代码时和使用Postman测试接口时。我们下面来一一了解:

一、前端表单提交时

application/x-www-form-urlencoded

表单代码:

<form action="http://localhost:8888/task/" method="POST">
First name: <input type="text" name="firstName" value="Mickey&"><br>
Last name: <input type="text" name="lastName" value="Mouse "><br>
<input type="submit" value="提交">
</form>

通过测试发现可以正常访问接口,在Chrome的开发者工具中可以看出,表单上传编码格式为application/x-www-form-urlencoded(Request Headers中),参数的格式为key=value&key=value

 
image.png

我们可以看出,服务器知道参数用符号&间隔,如果参数值中需要&,则必须对其进行编码。编码格式就是application/x-www-form-urlencoded将键值对的参数用&连接起来,如果有空格,将空格转换为+加号;有特殊符号,将特殊符号转换为ASCII HEX)。

application/x-www-form-urlencoded是浏览器默认的编码格式。对于Get请求,是将参数转换?key=value&key=value格式,连接到url后

ps:可以在这个网址测试表单:http://www.runoob.com/try/try.php?filename=tryhtml_form_submit

multipart/form-data

那么当服务器使用multipart/form-data接收POST请求时,服务器怎么知道每个参数的开始位置和结束位置呢?

<form action="http://localhost:8888/task/" method="POST" enctype="multipart/form-data">
First name: <input type="text" name="firstName" value="Mickey&"><br>
Last name: <input type="text" name="lastName" value="Mouse "><br>
<input type="submit" value="提交">
</form>

我们在开发者工具中可以看出multipart/form-data不会对参数编码,使用的boundary(分割线),相当于&boundary的值是----Web**AJv3

 
image.png

文件上传

上传文件也要指定编码格式为multipart/form-data

<form action="http://localhost:8888/testFile" enctype="multipart/form-data" method="POST">
<input type="file" name="file">
<input type="submit" value="提交">
</form>

如果是SpringMVC项目,要服务器能接受multipart/form-data类型参数,还要在spring上下文配置以下内容,SpringBoot项目则不需要

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
</bean>

我们可以通过FormData对象模拟表单提交,用原始的XMLHttpRequest来发送数据,让我们可以在Chrome开发工具中查看到具体格式:

<form id="form">
First name: <input type="text" name="firstName" value="Mickey"><br>
Last name: <input type="text" name="lastName" value="Mouse"><br>
<input type="file" name="file"><br>
</form> <button onclick="submitForm()">提交</button> <script>
function submitForm() {
var formElement = document.getElementById("form"); var xhr = new XMLHttpRequest();
xhr.open("POST", "/task/testFile");
xhr.send(new FormData(formElement));
}
</script>

格式如下:

 
image.png

二、调用接口代码时

1、在代码中使用application/x-www-form-urlencoded编码格式设置Request属性调用接口,可以如下实现:

private static String doPost(String strUrl, String content) {
String result = ""; try {
URL url = new URL(strUrl);
//通过调用url.openConnection()来获得一个新的URLConnection对象,并且将其结果强制转换为HttpURLConnection.
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
//设置连接的超时值为30000毫秒,超时将抛出SocketTimeoutException异常
urlConnection.setConnectTimeout(30000);
//设置读取的超时值为30000毫秒,超时将抛出SocketTimeoutException异常
urlConnection.setReadTimeout(30000);
//将url连接用于输出,这样才能使用getOutputStream()。getOutputStream()返回的输出流用于传输数据
urlConnection.setDoOutput(true);
//设置通用请求属性为默认浏览器编码类型
urlConnection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//getOutputStream()返回的输出流,用于写入参数数据。
OutputStream outputStream = urlConnection.getOutputStream();
outputStream.write(content.getBytes());
outputStream.flush();
outputStream.close();
//此时将调用接口方法。getInputStream()返回的输入流可以读取返回的数据。
InputStream inputStream = urlConnection.getInputStream();
byte[] data = new byte[1024];
StringBuilder sb = new StringBuilder();
//inputStream每次就会将读取1024个byte到data中,当inputSteam中没有数据时,inputStream.read(data)值为-1
while (inputStream.read(data) != -1) {
String s = new String(data, Charset.forName("utf-8"));
sb.append(s);
}
result = sb.toString();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
} return result;
} public static void main(String[] args) {
String str = doPost("http://localhost:8888/task/", "firstName=Mickey%26&lastName=Mouse ");
System.out.println(str);
}

2、在代码中使用multipart/form-data编码格式设置Request属性调用接口时,其中boundary的值可以在设置Content-Type时指定,让服务器知道如何拆分它接受的参数。通过以下代码的调用接口:

private static String doPost(String strUrl, Map<String, String> params, String boundary) {
String result = ""; try {
URL url = new URL(strUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(30000);
urlConnection.setReadTimeout(30000);
urlConnection.setDoOutput(true);
//设置通用请求属性为multipart/form-data
urlConnection.setRequestProperty("content-type", "multipart/form-data;boundary=" + boundary);
DataOutputStream dataOutputStream = new DataOutputStream(urlConnection.getOutputStream()); for (String key : params.keySet()) {
String value = params.get(key);
//注意!此处是\r(回车:将当前位置移到本行开头)、\n(换行:将当前位置移到下行开头)要一起使用
dataOutputStream.writeBytes("--" + boundary + "\r\n");
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + encode(key) + "\"\r\n");
dataOutputStream.writeBytes("\r\n");
dataOutputStream.writeBytes(encode(value) + "\r\n");
}
//最后一个分隔符的结尾后面要跟"--"
dataOutputStream.writeBytes("--" + boundary + "--");
dataOutputStream.flush();
dataOutputStream.close();
InputStream inputStream = urlConnection.getInputStream();
byte[] data = new byte[1024];
StringBuilder sb = new StringBuilder();
while (inputStream.read(data) != -1) {
String s = new String(data, Charset.forName("utf-8"));
sb.append(s);
}
result = sb.toString();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
} return result;
} private static String encode(String value) throws UnsupportedEncodingException {
return URLEncoder.encode(value, "UTF-8");
} public static void main(String[] args) {
Map<String, String> params = new HashMap<>();
params.put("firstName", "Mickey");
params.put("lastName", "Mouse"); //自定义boundary,有两个要求:使用不会出现在发送到服务器的HTTP数据中的值;并在请求消息中的分割位置都使用相同的值
String boundary = "abcdefg";
String str = doPost("http://localhost:8888/testFile", params, boundary);
System.out.println(str);
}

通过debug,可以看出dataOutputStream的值如下:

 
image.png

三、使用Postman测试接口时

1、POST请求 -> Body -> x-www-form-urlencoded

 
image.png

当切换为x-www-form-urlencoded时,Headers会自动添加Content-Type:application/x-www-form-urlencoded

 
image.png

当请求Send后,此时点Code,可以查看到和Chrome开发工具中(Request Headers处的Content-Type和Form Data)一样的数据

 
image.png

2、POST请求 -> Body -> form-data

相当于html表单请求,value可为Text或文件。

 
image.png

可以不用手动指定编码格式,也可以指定编码为multipart/form-data

 
image.png

划线处的分割线应该是被省略了。

 
image.png

可以更改左上角的类型,来查看相应的Headers代码,常见的是下面三种:

Java OK HTTP

 
image.png

JavaScript Jquery AJAX

 
 

JavaScript XHR

 
image.png

总结

POST请求的两种编码格式:application/x-www-urlencoded是浏览器默认的编码格式,用于键值对参数,参数之间用&间隔;multipart/form-data常用于文件等二进制,也可用于键值对参数,最后连接成一串字符传输(参考Java OK HTTP)。除了这两个编码格式,还有application/json也经常使用。

接口代码

@RequestMapping("/task")
public class TaskController { @RequestMapping("/")
public String index(String firstName, String lastName) {
return firstName + lastName;
} @RequestMapping("/testFile")
public String testFile(String firstName, String lastName, MultipartFile file) {
String result = firstName + lastName;
if (file != null) {
result += (file.getOriginalFilename() != null) ? file.getOriginalFilename() : "";
}
return result;
}
}

参考网址

HTML <form> 标签的 enctype 属性:http://www.w3school.com.cn/tags/att_form_enctype.asp

HttpUrlConnection 基础使用:https://www.cnblogs.com/libertycode/p/5979260.html

SpringMvc接收multipart/form-data 传输的数据 及 PostMan各类数据类型的区别:https://www.cnblogs.com/ifindu-san/p/8251370.html#undefined

What is the boundary in multipart/form-data?:https://stackoverflow.com/questions/3508338/what-is-the-boundary-in-multipart-form-data

作者:DeppWang
链接:https://www.jianshu.com/p/53b5bd0f1d44
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Post请求的两种编码格式:application/x-www-form-urlencoded和multipart/form-data的更多相关文章

  1. HTTP POST 请求的两种编码格式:application/x-www-form-urlencoded 和 multipart/form-data

    在常见业务开发中,POST 请求常常在这些地方使用:前端表单提交时.调用接口代码时和使用 Postman 测试接口时.我们下面来一一了解: 一.前端表单提交时 application/x-www-fo ...

  2. C#中Post请求的两种方式发送参数链和Body的

    POST请求 有两种方式 一种是组装key=value这种参数对的方式 一种是直接把一个字符串发送过去 作为body的方式 我们在postman中可以看到 sfdsafd sdfsdfds publi ...

  3. .net中对HTTP请求的两种请求:Get和Post的操作

    .net中对HTTP请求的简单操作总结 第一部分,HTTP协议的简单了解 一.           什么是HTTP协议 超文本传输协议 (HTTP-Hypertext transfer protoco ...

  4. 第二节:SSL证书的申请、配置(IIS通用)及跳转Https请求的两种方式

    一. 相关概念介绍 1. SSL证书服务 SSL证书服务由"服务商"联合多家国内外数字证书管理和颁发的权威机构.在xx云平台上直接提供的服务器数字证书.您可以在阿里云.腾讯云等平台 ...

  5. 解决 SharePoint 2010 拒绝访问爬网内容源错误的小技巧(禁用环回请求的两种方式)

    这里有一条解决在SharePoint 2010搜索爬网时遇到的“拒绝访问错误”的小技巧. 首先要检查默认内容访问帐户是否具有相应的访问权限,或者添加一条相应的爬网规则.如果目标资源库是一个ShareP ...

  6. iOS- 网络请求的两种常用方式【GET & POST】的区别

    GET和POST 网络请求的两种常用方式的实现[GET & POST] –GET的语义是获取指定URL上的资源 –将数据按照variable=value的形式,添加到action所指向的URL ...

  7. GET和POST是HTTP请求的两种基本方法,区别是什么!?

    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...

  8. CAN总线常见的两种编码格式(Intel/Motorola)

    在汽车电子行业的开发或者测试中,我们经常会看到CAN总线信号的常见的两种编码格式:Intel格式与Motorola格式. 讲解这两种格式之前,我们先来了解一些大端模式和小端模式,会对后面理解这两种编码 ...

  9. ASP.NET MVC 实现AJAX跨域请求的两种方法

    通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据的加载,例如Google. 在ASP.NET MVC 框 ...

随机推荐

  1. 题解【CJOJ1371】[IOI2002]任务安排

    P1371 - [IOI2002]任务安排 Description N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分 ...

  2. java测试框架详细说明-mvn+testng+allure

    java测试框架 mvn+testng+allure 1.mvn代码目录结构 2.testng框架 2.1 testng.xml配置 2.2 注解 3.allure插件,方便报告阅览 4.配置文件.p ...

  3. How To Use These LED Garden Lights

    Are you considering the lighting options for the outdoor garden? Depending on how you use it, LED ga ...

  4. fiddler中文乱码解决方案

    只用添加一个注册表变量就行 cmd窗口执行regedit命令,在弹出的注册表编辑界面找到fiddler 右击新建一个字符传值 HeaderEncodingGBK 结果如上图右所示~ 重启fiddler ...

  5. SpringMVC--使用hibernate validator数据校验

    JSR 303 Spring3开始支持JSR 303 验证框架,JSR303是Java为Bean数据合法性校验所提供的标准框架.JSR 303 支持XML和注解风格的验证,通过在Bean属性上标注类似 ...

  6. vue中的回到顶部

    <template> <div class="main"> <div class="content">灰色部分是内容部分&l ...

  7. 吴裕雄 python 机器学习——集成学习梯度提升决策树GradientBoostingRegressor回归模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...

  8. Dictionary-Guided Editing Networks for Paraphrase Generation解读

    过程:输入->检索->编码->解码 解释:检索:输入一句话x,首先从PPDB中检索出M * 10 个释义对,并排序,记为x的本地字典: 编码:将所有的释义对编码为向量,单字转为字向量 ...

  9. APP测试用例

    日程管理APP测试用例 测试编号 测试用例 实际结果 期望结果 测试结果(Pass/Failed) 备注 NO.1 输入正确的用户名和密码点击登录 登录成功 登录成功 Pass NO.2 点击注册界面 ...

  10. 什么是this指针?this的几种指向

    在JavaScript中,this指针是在创建时,由系统默认生成的两个隐式参数之一(另一个是arguments). this指针指向与该函数调用进行隐式关联的一个对象,该对象被称为“函数上下文”. t ...