?正文如下?
來源:juejin.im/post/6860253625030017031
曾經(jīng)遇到的面試題,覺得挺有意思,來說下我的答案及思考過程。首先,我們要知道的是,圖片一般有兩種傳輸方式:base64 和 file對象。
base64 的本質是字符串,而 GET 請求的參數(shù)在 url 里面,所以直接把圖的 base64 數(shù)據(jù)放到 url 里面,就可以實現(xiàn) GET 請求傳圖片。input 輸入框拿到的圖是 file 對象,圖片 file 對象轉 base64 :const getBase64 = img => { return new Promise((resolve,reject) => { const reader = new FileReader(); reader.onload = e => { resolve(e.target.result); }; reader.onerror = e => reject(e); reader.readAsDataURL(img); })}
問題來了,GET 請求的 url 長度是有限制的,不同的瀏覽器長度限制不一樣,最長的大概是 10k 左右,根據(jù) base64 的編碼原理,base64圖片大小比原文件大小大 1/3,所以說 base64 只能傳一些非常小的小圖,大圖的 base64 太長會被截斷。但其實這個長度限制是瀏覽器給的,而不是 GET 請求本身,也就說,在服務端,GET 請求長度理論上無限長,也就是可以傳任意大小的圖片。
<form?action="http://localhost:8080/"?method="get"> <input type="file" name="logo"> <input type="submit">form>
選擇圖片,然后提交表單,能提交成功,但是接口收不到文件。請求的 url 會變成 http://localhost:8080/?logo=xxx.png,但是不會攜帶圖片數(shù)據(jù)。正常情況,file 對象數(shù)據(jù)是放在POST請求的 body 里面,并且是 form-data 編碼。那么 GET 請求能否有 body 體呢?答案是可以有。GET 和 POST 并沒有本質上的區(qū)別,他們只是 HTTP 協(xié)議中兩種請求方式,僅僅是報文格式不同(或者說規(guī)范不同)。做過底層開發(fā)的同事可能比較熟悉,之前我們C語言的同事和我講,我們的 HTTP 請求,他們收到是這樣子的:
舉個栗子, 一個普通的 GET 請求,他們收到是這樣的:
GET?/test/?sex=man&name=zhangsan?HTTP/1.1Host: http://localhost:8080Accept: application/json, text/plain, */*Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: Keep-Alive
POST?/add?HTTP/1.1Host: http://localhost:8080Content-Type: application/x-www-form-urlencodedContent-Length: 40Connection: Keep-Alive
sex=man&name=Professional
同樣,DELETE、PUT、PATCH 請求,也都是這樣的報文。底層解析這個報文的時候,并不關心是什么請求,所以說 GET請求也可以有body 體,也可以傳 form-data 數(shù)據(jù)。有興趣的可以拿 postman(我用的版本是 v7.30.1) 試一下,看看 GET 請求傳圖片,接口能不能收到圖片文件:
GET 請求能不能帶 body 這個事是由 HTTP 協(xié)議來定義的。所謂協(xié)議就是大家共同遵守的一套規(guī)則,你不遵守某一規(guī)則有時候確實不會有大問題,但是其行為表現(xiàn)是什么就不得而知了。協(xié)議帶來規(guī)范化,規(guī)范化帶來高效。事實是 HTTP 1.1 的 RFC 文檔里沒有禁止 GET 請求帶 body ,但是也沒有定義 GET 請求 body 的語義。A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
或者說,真要 get 傳圖片作為方案的話,需要打通上面兩個關鍵技術問題。面試現(xiàn)場也可以再加一些Blob、TypedArray、圖片壓縮方案之類的。