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[] {};
}