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

Keywords: Mobile encoding Java Javascript ascii

In common business development, POST requests are often used in these places: when front-end forms are submitted, when interface code is invoked, and when the Postman test interface is used.Let's take a look:

1. When a 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="Submit">
</form>

The test found that the interface was accessible properly. As you can see from the Chrome developer tools, 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 symbolized &spaced and that if &is required in the parameter values, it must be encoded.The encoding format is application/x-www-form-urlencoded (links parameters of key-value pairs with & and converts spaces to + plus if there are spaces; converts special symbols to ASCII HEX values if there are special symbols).

application/x-www-form-urlencoded is the default encoding format for browsers.For Get requests, is the parameter converted? Key=value&key=value format, after connecting to the url

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

multipart/form-data

So how does the server know where each parameter begins and ends when it receives POST requests using multipart/form-data?

<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="Submit">
</form>

We can see from the developer's tools that multipart/form-data does not encode parameters and uses a boundary (splitter line), which is equivalent to the value of & boundary - --- Web**AJv3.

 
image.png

File Upload

The uploaded file also specifies the encoding format as multipart/form-data.

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

If it is a SpringMVC project, the SpringBoot project does not need to be able to accept multipart/form-data type parameters on the server and configure the following in the spring context.

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

We can simulate form submission through the FormData object, send data using the original XMLHttpRequest, and let us see the 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()">Submit</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

2. When calling interface code

1. Use the application/x-www-form-urlencoded encoding format to set the Request property in the code to invoke the interface, which can be implemented as follows:

private static String doPost(String strUrl, String content) {
        String result = "";

        try {
            URL url = new URL(strUrl);
            //A new URLConnection object is obtained by calling url.openConnection(), and the result is cast to HttpURLConnection.
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            //Setting the connection's timeout value to 30,000 milliseconds throws a SocketTimeoutException exception
            urlConnection.setConnectTimeout(30000);
            //Set the read timeout to 30,000 milliseconds, which throws the SocketTimeoutException exception
            urlConnection.setReadTimeout(30000);
            //Use url connections for output so that getOutputStream () can be used.The output stream returned by getOutputStream() is used to transfer data
            urlConnection.setDoOutput(true);
            //Set the Common Request property to the default browser encoding type
            urlConnection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            //The output stream returned by getOutputStream() to write parameter data.
            OutputStream outputStream = urlConnection.getOutputStream();
            outputStream.write(content.getBytes());
            outputStream.flush();
            outputStream.close();
            //The interface method is invoked.The input stream returned by getInputStream() reads the returned data.
            InputStream inputStream = urlConnection.getInputStream();
            byte[] data = new byte[1024];
            StringBuilder sb = new StringBuilder();
            //InputStream reads 1024 byte s into the data each time. When there is no data in inputSteam, the inputStream.read(data) value is -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 calling an interface using the multipart/form-data encoding format to set the Request property in code, the boundary value can be specified when setting the Content-Type to let the server know how to split the parameters it accepts.Call 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);
        //Set the universal request property to 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);
            //Be careful!Here are \r (Enter: Move the current position to the beginning of the line), \n (Break: Move the current position to the beginning of the line) to be used together
            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");
        }
        //The last separator ends with'--'
        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");

    //Custom boundaries have two requirements: to use values that do not appear in HTTP data sent to the server; and to use the same values for split positions in request messages
    String boundary = "abcdefg";
    String str = doPost("http://localhost:8888/testFile", params, boundary);
    System.out.println(str);
}

From debug, you can see the following values for dataOutputStream:

 
image.png

3. When using Postman test interface

1. POST Request-> Body-> x-www-form-urlencoded

 
image.png

When you switch to x-www-form-urlencoded, Headers automatically add Content-Type:application/x-www-form-urlencoded

 
image.png

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

 
image.png

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

Equivalent to an html form request, the value can be a Text or a file.

 
image.png

You can either specify the encoding format without manually specifying it, or you can specify the encoding as multipart/form-data

 
image.png

The dividing line at the line should be omitted.

 
image.png

You can change the type in the upper left corner to see the corresponding Headers code, which is common in the following three types:

Java OK HTTP:

 
image.png

JavaScript Jquery AJAX:

 
 

JavaScript XHR:

 
image.png

summary

Two encoding formats for POST requests: application/x-www-urlencoded, which is the default encoding format for browsers, is used for key-value pair parameters with an interval between them; multipart/form-data, which is commonly used in binary formats such as files, is also used for key-value pair parameters, and is connected to a string of character transfers (refer to Java OK HTTP).In addition to these two encoding formats, application/json is also 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;
    }
}

Reference Web Site

HTML <form> Labeled enctype Attributes: http://www.w3school.com.cn/tags/att_form_enctype.asp

HttpUrlConnection Basic Use: https://www.cnblogs.com/libertycode/p/5979260.html

SpringMvc Receive multipart/form-data Data transferred and PostMan Differences between data types: 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-t


Author: DeppWang
Link: https://www.jianshu.com/p/53b5bd0f1d44
Source: Short Book
Copyright belongs to the author.For commercial reprinting, please contact the author for authorization. For non-commercial reprinting, please indicate the source.

Posted by buzzed_man on Thu, 13 Feb 2020 20:00:26 -0800