application/x-www-form-urlencode
我們在提交表單的時候,form表單參數中會有一個enctype的參數。enctype指定了HTTP請求的Content-Type。
默認情況下,HTML的form表單的enctype=application/x-www-form-urlencoded。
application/x-www-form-urlencoded是指表單的提交,并且將提交的數據進行urlencode。默認情況下,我們所有的表單提交都是通過這種默認的方式實現的。
在火狐瀏覽器下,我們可以看一下提交數據的過程:
我們可以看到Content-type:
Content-Type
application/x-www-form-urlencoded; charset=UTF-8
然后繼續看一下原始請求數據,原始的請求數據被urlencode了。
Ajax默認也是通過HTTP application/x-www-form-urlencoded提交數據。可以看下Jquery的源碼:
multipart/form-data
一般情況下,我們如果要在表單中上傳文件,一般會將form的enctype參數設置為multipart/form-data。這種方式只支持POST的請求方式。
Contype-Type=multipart/form-data情況的時候,都會通過一個特殊的字符串來將原始POST數據進行分割。
我們可以看到下面的請求中Content-type的類型:
Content-Type
multipart/form-data; boundary=---------------------------66841812532223
其中boundary=---------------------------66841812532223,為分割符號。
其中數據塊開始的分隔符 =={boundary} 會在前面加上“==”
數據塊結束的分隔符 =={boundary}== 會在后面加上“==”
繼續看下原始數據,我們可以清晰的看到,各種請求數據被boundary值進行了分割。
雖然這些知識點很早就知道了,但是知其然知其所以然可以讓我們深入每一個技術細節。
application/json
有些時候,我們會直接提交Content-type是json數據格式的請求。
例如:
var data = {'title':'test', 'sub' : [1,2,3]};
$http.post(url, data).success(function(result) { ...
});
請求:
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8 {"title":"test","sub":[1,2,3]}
這種情況下,請求的Content-Type是Json的數據格式,http body中的內容就是請求的json數據。
如果是php的話,需要通過 php://input來接收POST中的原始數據信息。
如果是Java,則需要下面的方式來讀取HTTP 請求BODY中的數據
protected void processRequest(HttpServletRequest request,HttpServletResponse response) {try {request.setCharacterEncoding("UTF-8");int size = request.getContentLength(); System.out.println(size); InputStream is = request.getInputStream(); byte[] reqBodyBytes = readBytes(is, size); String res = new String(reqBodyBytes); System.out.println(res); response.setContentType("text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.getOutputStream().write(res.getBytes("utf-8")); response.flushBuffer(); } catch (Exception e) {}
}public static final byte[] readBytes(InputStream is, int contentLen) {if (contentLen > 0) {int readLen = 0; int readLengthThisTime = 0; byte[] message = new byte[contentLen]; try {while (readLen != contentLen) {readLengthThisTime = is.read(message, readLen, contentLen - readLen);if (readLengthThisTime == -1) {// Should not happen. break;}readLen += readLengthThisTime;}return message;} catch (IOException e) {// Ignore // e.printStackTrace(); } }return new byte[] {};
}