Http post Request Message format analysis and Java Implementation of file upload, packet File Upload
During development, the most popular HTTP request methods are GET and POST. GET is used to obtain data from the server, and POST is mainly used to submit some form data to the server, such as file upload. The most troublesome thing we encounter when using HTTP requests is to construct the HTTP message format for file upload. This format is simple but error-prone. Today, let's take a look at the http post Message format and simulate File Upload requests using Java.
First, let's look at a POST packet request, and then we will analyze it in detail.
POST Message format
POST/api/feed/HTTP/1.1Accept-Encoding: gzipContent-Length: 225873Content-Type: multipart/form-data; boundary = OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBpHost: www. myhost. comConnection: Keep-Alive -- OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBpContent-Disposition: form-data; name = "lng" Content-Type: text/plain; charset = UTF-8Content-Transfer-Encoding: 8bit116. 361545 -- OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBpContent-Disposition: form-data; name = "lat" Content-Type: text/plain; charset = UTF-8Content-Transfer-Encoding: 8bit39. 979006 -- OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBpContent-Disposition: form-data; name = "images"; filename = "/storage/emulated/0/Camera/jdimage/1xh0e3yyfmpr2e35tdowbavrx.jpg" Content-Type: application/octet-streamContent-Transfer-Encoding: binary here is the binary data of the image -- OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp --
Here we submit the longitude, latitude and an image (the image data is relatively long and messy, Which is omitted here ).
Format analysis request header analysis we first look at the first line in the message format:
POST /api/feed/ HTTP/1.1
This line shows the Request Method of this request, that is, the POST method. The sub-path to be requested is/api/feed/. For example, our server address is www.myhost.com, then, the complete path of our request is www.myhost.com/api/feed/. at the end, we will describe the HTTP protocol with the ID 1.1.
Accept-Encoding: gzipContent-Length: 225873Content-Type: multipart/form-data; boundary=OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBpHost: www.myhost.comConnection: Keep-Alive
These headers mean that the data returned by the server must be compressed using gzip, the request content length is 225873, the content type is "multipart/form-data", and the request parameter separator (boundary) for the OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp, the request's root domain name is www.myhost.com, And the HTTP connection method is persistent connection (Keep-Alive ).
One thing to note here is the separator, that is, boundary. Boundary is used as the boundary between Request Parameters. For example, a definite boundary must be set between parameter 1 and parameter 2 so that the server can correctly parse parameters 1 and 2. But the separator is not just boundary, but the following format: -- + boundary. For example, the boundary here is the OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp, then the parameter separator is:
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Whether boundary itself has this "--", this "--" cannot be omitted.
We know that the HTTP protocol adopts the "request-response" mode. When the common mode is used, that is, the non-KeepAlive mode, a new connection is required for each request/response client and server, disconnect immediately after completion (the HTTP protocol is connectionless). When the Keep-Alive mode (also known as persistent connection and connection reuse) is used, the Keep-Alive function keeps the client-to-server connection valid. When there are subsequent requests to the server, the Keep-Alive function avoids or reestablishes the connection.
For example, the left side is the case of disabling Keep-Alive. Each request requires a connection and then the connection is closed. The right side is the Keep-Alive, which maintains the connection after the first request is established, then, you do not need to establish or close the connection each time. Enabling the Keep-Alive mode is certainly more efficient and has higher performance, because it avoids the overhead of establishing/releasing connections.
In http 1.0, It is disabled by default. You must add "Connection: Keep-Alive" to the http header to enable Keep-Alive. In http 1.1, Keep-Alive is enabled by default, if "Connection: close" is added, it is closed. Currently, most browsers use the http1.1 Protocol. That is to say, Keep-Alive connection requests are initiated by default. Therefore, whether a complete Keep-Alive connection can be completed depends on the server settings.
Request Entity Analysis The Request Entity is actually the parameter list of the http post request. Each parameter starts with a request separator, that is, -- + boundary. For example, the following parameter.
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBpContent-Disposition: form-data; name="lng"Content-Type: text/plain; charset=UTF-8Content-Transfer-Encoding: 8bit116.361545
The first behavior above -- OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp, that is -- plus the boundary content, and finally add a line feed (this line feed cannot be omitted), the line feed string is represented as "\ r \ n ". The second behavior is Content-Disposition and parameter name. Here the parameter name is lng, that is, longitude. Content-Disposition provides a default file name when you want to save the requested Content as a file. The third behavior is Content-Type, that is, the Type of the object that the WEB server tells the browser to respond to, as well as the specified character encoding for the UTF-8. The fourth line describes the transmission format of the entity object (entity) attached to the request and response. The simple text data is set to 8 bit, set the file parameters to binary. After adding two line breaks, it is the specific content of the parameter. For example, the parameter content here is 116.361545. Note that "\ r \ n" is used between each line, and the last line and the parameter content are two line breaks. File parameters are in the same format, but the content of file parameters is byte streams. Note that there are two differences between common text parameters and file parameters, because the content format is different. Common parameters:
Content-Type: text/plain; charset=UTF-8Content-Transfer-Encoding: 8bit
File parameters:
Content-Type: application/octet-streamContent-Transfer-Encoding: binary
The last line of the parameter object is -- plus boundary plus --, And the last line feed. The format here is -- OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp --. Simulate File Upload requests
Public static void uploadFile (String fileName) {try {// linefeed final String newLine = "\ r \ n"; final String boundaryPrefix = "--"; // define the Data Separator String BOUNDARY = "======== 7d4a6d158c9"; // The server domain name URL = new url ("www.myhost.com "); httpURLConnection conn = (HttpURLConnection) url. openConnection (); // set to POST conn. setRequestMethod ("POST"); // The following two rows of conn must be set to send a POST request. setDoOutput (true); conn. setDoInput (tru E); conn. setUseCaches (false); // set the request header parameter conn. setRequestProperty ("connection", "Keep-Alive"); conn. setRequestProperty ("Charsert", "UTF-8"); conn. setRequestProperty ("Content-Type", "multipart/form-data; boundary =" + BOUNDARY); OutputStream out = new DataOutputStream (conn. getOutputStream (); // Upload File file = new File (fileName); StringBuilder sb = new StringBuilder (); sb. append (boundaryPrefix); sb. Append (BOUNDARY); sb. append (newLine); // file parameter. The photo parameter name can be modified at will. append ("Content-Disposition: form-data; name = \" photo \ "; filename = \" "+ fileName +" \ "" + newLine); sb. append ("Content-Type: application/octet-stream"); // two line breaks are required after the parameter header is set, followed by the parameter Content sb. append (newLine); sb. append (newLine); // write the data in the parameter header to the output stream out. write (sb. toString (). getBytes (); // data input stream, used to read file data DataInputStream in = new DataInputStream (new F IleInputStream (file); byte [] bufferOut = new byte [1024]; int bytes = 0; // 1 kb of data is read each time, and write the file data to the output stream while (bytes = in. read (bufferOut ))! =-1) {out. write (bufferOut, 0, bytes);} // Add a line break out. write (newLine. getBytes (); in. close (); // defines the last data separation line, that is, adding BOUNDARY and --. Byte [] end_data = (newLine + boundaryPrefix + BOUNDARY + boundaryPrefix + newLine ). getBytes (); // write the end identifier out. write (end_data); out. flush (); out. close (); // define the BufferedReader input stream to read the URL response // BufferedReader reader = new BufferedReader (new InputStreamReader (// conn. getInputStream (); // String line = null; // while (line = reader. readLine ())! = Null) {// System. out. println (line); //} catch (Exception e) {System. out. println ("an Exception occurred when sending a POST request! "+ E); e. printStackTrace ();}}
Use Apache Httpmime to upload files
/*** @ Param fileName image path */public static void uploadFileWithHttpMime (String fileName) {// define the request url String uri = "www.myhost.com "; // instantiate the http client HttpClient httpClient = new DefaultHttpClient (); // instantiate the post submission method HttpPost post = new HttpPost (uri ); // Add the json parameter try {// instantiate the parameter object MultipartEntity params = new MultipartEntity (); // image text parameter params. addPart ("textParams", new StringBody ("{'user _ name': 'user name ',' Channel_name ': 'Channel _ address':' (123.4, 30.6) '} ", Charset. forName ("UTF-8"); // sets the File to be uploaded file File = new file (fileName); // The File parameter content FileBody fileBody = new FileBody (file ); // Add the file parameter params. addPart ("photo", fileBody); params. addPart ("photoName", new StringBody (file. getName (); // Add the parameter to post in the post Request body. setEntity (params); // execute the post request and obtain the returned object [in this step, our request starts] HttpResponse resp = httpClient.exe cute (p Ost); // parse the returned request result HttpEntity entity = resp. getEntity (); InputStream is = entity. getContent (); BufferedReader reader = new BufferedReader (new InputStreamReader (is); StringBuffer buffer = new StringBuffer (); String temp; while (temp = reader. readLine ())! = Null) {buffer. append (temp);} System. out. println (buffer);} catch (UnsupportedEncodingException e) {e. printStackTrace ();} catch (ClientProtocolException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} catch (IllegalStateException e) {e. printStackTrace ();}}HttpMime. jar: Download The httpClient compressed package. httpmime. jar is included in the package.