一旦項(xiàng)目中需要文件上傳,你就能很熟練的在表單上增加
enctype="multipart/form-data"屬性,然而你是否思考過為什么需要這樣做呢?
HTTP POST 數(shù)據(jù)傳輸
HTTP協(xié)議建立在TCP/IP協(xié)議之上的應(yīng)用層規(guī)范,規(guī)范定義請(qǐng)求分為:狀態(tài)行、請(qǐng)求頭、消息主體,用chrome dev tool可以看到:

其中General對(duì)應(yīng)于狀態(tài)行,request Headers對(duì)應(yīng)于請(qǐng)求頭,formData對(duì)應(yīng)于請(qǐng)求主體(還有可能是payload)
這是chrome dev tool 解析的結(jié)果,實(shí)際傳輸中并不是如此
對(duì)于post請(qǐng)求,協(xié)議要求數(shù)據(jù)必須放到消息主體中進(jìn)行傳輸(有別于get請(qǐng)求將數(shù)據(jù)附在url之后,即放入?yún)f(xié)議頭中傳輸),那么問題來了,消息主體中的數(shù)據(jù)以什么數(shù)據(jù)格式傳輸呢?這就要發(fā)揮enctype的聲明作用了
Content-Type & enctype
如果你足夠細(xì)心,你會(huì)發(fā)現(xiàn)請(qǐng)求頭中有一個(gè)Content-type字段

這個(gè)字段聲明了消息主體中數(shù)據(jù)的編碼方式,application/x-www-form-urlencoded;charset=utf-8表明提交的數(shù)據(jù)按照key1=val1&key2=val2格式編碼,例如:
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
后臺(tái)收到請(qǐng)求,就可以根據(jù)請(qǐng)求頭中的Content-Type來對(duì)請(qǐng)求數(shù)據(jù)解碼
這一步往往對(duì)開發(fā)者來說是透明的,那是因?yàn)橐话愕姆?wù)器框架都把這事做了,是不是有g(shù)et-新技能了~~
然而,這跟enctype有什么關(guān)系呢?
在表單中設(shè)置enctype屬性,也就指定了請(qǐng)求頭中Content-type的值,默認(rèn)不設(shè)置enctype的情況下,Content-type為application/x-www-form-urlencoded;charset=utf-8
回到題引,文件上傳的時(shí)候,我們會(huì)在表單中設(shè)置enctype="multipart/form-data",此時(shí)請(qǐng)求信息大概為:
//請(qǐng)求頭
//Content-Type除了指定編碼形式為multipart/form-data
//還指定了此處的分隔符(boundary)
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryER0jqXh3Qttw3ldU
//請(qǐng)求體
------WebKitFormBoundaryER0jqXh3Qttw3ldU
Content-Disposition: form-data; name="file"; filename="箭頭向上.png"
Content-Type: image/png
//此處是文件二進(jìn)制內(nèi)容
------WebKitFormBoundaryER0jqXh3Qttw3ldU--
由于涉及到文件,內(nèi)容比較大,使用application/x-www-form-urlencoded;charset=utf-8的方式來分割就不盡如人意了,采取一個(gè)分割串的形式來分割還是比較合適的,請(qǐng)求頭中定義了分割串,請(qǐng)求體中每個(gè)參數(shù)都被夾在分隔符之間(--boundary開始,--boundary--結(jié)束)
另外常用的enctype還有application/json和text/xml,顧名思義,分別是json和xml的傳輸格式,這里就不細(xì)說了
總結(jié)
雖然不知道這些也不影響coding,但是揭開面紗還是很有意義的
歡迎留言討論,如果對(duì)您有幫助,請(qǐng)留個(gè)贊~~