作者:沉末
前言
曾經遇到的面試題,覺得挺有意思,來說下我的答案及思考過程。
首先,我們要知道的是,圖檔一般有兩種傳輸方式:
base64
和
file
對象。
base64 圖檔
圖檔的
base64
編碼想必大家都見過:
base64
的本質是字元串,而
GET
請求的參數在
url
裡面,是以直接把圖的
base64
資料放到
url
裡面,就可以實作
GET
請求傳圖檔。
input
輸入框拿到的圖是
file
對象,圖檔
file
對象轉
base64
:
// img參數:file檔案或者blob
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 左右,根據
base64
的編碼原理,
base64
圖檔大小比原檔案大小大 1/3,是以說
base64
隻能傳一些非常小的小圖,大圖的
base64
太長會被截斷。但其實這個長度限制是浏覽器給的,而不是
GET
請求本身,也就說,在服務端,
GET
請求長度理論上無限長,也就是可以傳任意大小的圖檔。
file 對象
我們來看看這個場景:
<form action="http://localhost:8080/" method="get">
<input type="file" name="logo">
<input type="submit">
</form>
選擇圖檔,然後送出表單,能送出成功,但是接口收不到檔案。請求的
url
會變成
http://localhost:8080/?logo=xxx.png
,但是不會攜帶圖檔資料。正常情況,
file
對象資料是放在
POST
請求的
body
裡面,并且是
form-data
編碼。那麼
GET
請求能否有
body
體呢?答案是可以有。
GET
和
POST
并沒有本質上的差別,他們隻是
HTTP
協定中兩種請求方式,僅僅是封包格式不同(或者說規範不同)。做過底層開發的同僚可能比較熟悉,之前我們C語言的同僚和我講,我們的
HTTP
請求,他們收到是這樣子的:
舉個栗子, 一個普通的 GET 請求,他們收到是這樣的:
GET /test/?sex=man&name=zhangsan HTTP/1.1
Host: http://localhost:8080
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: Keep-Alive
POST 請求長這樣:
POST /add HTTP/1.1
Host: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
sex=man&name=Professional
同樣,
DELETE
、
PUT
、
PATCH
請求,也都是這樣的封包。底層解析這個封包的時候,并不關心是什麼請求,是以說
GET
請求也可以有
body
體,也可以傳
form-data
資料。有興趣的可以拿 postman 試一下,看看
GET
請求傳圖檔,接口能不能收到圖檔檔案:
結尾
綜上所述,GET 請求是可以傳圖檔的,但是 GET 和 POST 的規範還是要遵守的,如果有背景讓你這麼做,錘他就行了!