Two encoding formats for Post requests: application / x-www-form-urlencoded and multipart / form-data (transition)

Original link:

https://www.jianshu.com/p/53b5bd0f1d44

In common business development, POST requests are often used in these places: when submitting front-end forms, when calling interface code, and when using Postman to test the interface. Let's understand them one by one:

1. When the front-end form is submitted

application/x-www-form-urlencoded

Form code:

<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> 

Through testing, it is found that the interface can be accessed normally. It can be seen in Chrome's developer tools that the form upload encoding format is application/x-www-form-urlencoded(in Request Headers) and the parameter format is key=value&key=value.

 
image.png

We can see that the server knows that the parameters are &separated by symbols , and if required &in the parameter value , it must be encoded. The encoding format is application/x-www-form-urlencoded( connect the parameters of the key-value pairs with &, if there are spaces, convert the spaces to +plus signs; with special symbols, convert the special symbols into ASCII HEXvalues ).

application/x-www-form-urlencodedIs the browser's default encoding format. For the Get request, it is the parameter conversion ?key=value&key=valueformat, after connecting to the url

ps: You can test the form at this URL: http://www.runoob.com/try/try.php?filename=tryhtml_form_submit

multipart/form-data

So when the server uses to multipart/form-datareceive POST requests, how does the server know the start position and end position of each parameter?

<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> 

We can see in the developer tool that multipart/form-datathe parameter will not be encoded, and the value used is boundary(divider), which is equivalent to .&boundary----Web**AJv3

 
image.png

File Upload

Upload file must also specify the encoding format 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> 

If it is a multipart/form-dataSpring MVC project, if the server can accept the type parameter, the following content must also be configured in the spring context, which is not required for the Spring Boot project .

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

We can simulate the form submission through the FormData object and send the data with the original XMLHttpRequest, so that we can view the specific format in the Chrome development tool:

<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> 

The format is as follows:

 
image.png

Second, when calling the interface code

1. Use the application/x-www-form-urlencodedencoding format to set the Request attribute calling interface in the code , which can be implemented as follows:

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. When multipart/form-datasetting the Request property in the code using the encoding format to call the interface, boundarythe value in it can be specified when setting the Content-Type to let the server know how to split the parameters it accepts. Call the interface through the following code:

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); } 

Through debugging, we can see that the values ​​of dataOutputStream are as follows:

 
image.png

3. When using Postman to test the interface

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

 
image.png

When switched to x-www-form-urlencodedthe time, Headers are automatically addedContent-Type:application/x-www-form-urlencoded

 
image.png

When Send is requested, at this point Code, you can view the same data as the Chrome development tool (Content-Type and Form Data at Request Headers)

 
image.png

2. POST request-> Body-> form-data

Equivalent to html form request, value can be text or file.

 
image.png

You can not specify the encoding format manually, or you can specify the encoding asmultipart/form-data

 
image.png

The dividing line at the underline should be omitted.

 
image.png

You can change the type in the upper left corner to view the corresponding Headers code. The following three are common:

Java OK HTTP

 
image.png

JavaScript Jquery AJAX

 
 

JavaScript XHR

 
image.png

to sum up

Two encoding formats for POST requests: the application/x-www-urlencodeddefault encoding format for browsers, used for key-value pair parameters, with &intervals between parameters ; multipart/form-datacommonly used for files and other binary, can also be used for key-value pair parameters, and finally connected into a string of characters transmission ( (Refer to Java OK HTTP). In addition to these two encoding formats, there are application/jsonalso frequently used.

Interface code

@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; } }



Guess you like

Origin www.cnblogs.com/zhangshitong/p/12687512.html