功能需求
- 1.完成圖片的上傳和上傳之后圖片的預(yù)覽功能
遇到的問(wèn)題
- 1.使用html的src標(biāo)簽,可以直接發(fā)送請(qǐng)求。
- 通過(guò)html標(biāo)簽直接發(fā)送的請(qǐng)求沒(méi)有辦法添加header(a、img、form)
- 因此如果服務(wù)器需要check你的Headers中的Authorization來(lái)確定是否給當(dāng)前請(qǐng)求提供服務(wù),那么通過(guò)標(biāo)簽發(fā)送的請(qǐng)求必然不能被授予服務(wù)
- 2.圖片的上傳需要給服務(wù)器發(fā)送post請(qǐng)求,那么post請(qǐng)求的Headers以及body要求是什么呢?
完成功能
使用expressjs 作為服務(wù)器處理圖片上傳和預(yù)覽。使用antd上傳組件。
Q1:使用了antd upload組件本身帶的上傳功能,那么如何確定請(qǐng)求的路徑headers以及body呢?
-
A1: Upload組件本身帶了很多屬性
- action:確定上傳的路徑
- headers:確定上傳請(qǐng)求的headers
- name:確定了后端抓取文件需要訪問(wèn)的字段
- body:如果你沒(méi)有改寫(xiě)上傳的方法 body是確定的
{ fieldname: 'file', originalname: 'WechatIMG378.jpeg', encoding: '7bit', mimetype: 'image/jpeg' }
Q2:如何在文件上傳之前check文件的類(lèi)型和大?。?/p>
-
A2:antd的Upload組件包含屬性beforeUpload function這個(gè)函數(shù)會(huì)在上傳前被調(diào)用并且傳入上傳文件的對(duì)象file作為參數(shù)
- file.size: 以bytes為單位。
- 例子:要求文件大小小于3M
- file.size / 1024 / 1024 < 3
- 例子:要求文件大小小于3M
- file.type: 指的是文件發(fā)送的類(lèi)型
- 例子:
'image/jpeg', 'image/jpg', 'image/png', 'image/bmp'
- 例子:
- file.size: 以bytes為單位。
Q3: 對(duì)于圖片預(yù)覽部分我們不能直接使用img src,那么我們?cè)撛趺崔k?
-
A3:
- 首先src的值可以是什么呢?
- 1.是一個(gè)被webpack打包好的圖片
- 2.是一個(gè)可以請(qǐng)求到圖片的路徑
- 3.是圖片的base64編碼
-
但是前兩種方式都是通過(guò)發(fā)請(qǐng)求獲取的
- 這兩種方式的區(qū)別
- url:
- 1.需要發(fā)送一次請(qǐng)求
- 2.如果圖片文件的所有信息都不變俺么將會(huì)被緩存在瀏覽器中
- base64:
- 1.不需要發(fā)送請(qǐng)求直接內(nèi)嵌在html中
- 2.不能被瀏覽器緩存
- 3.當(dāng)圖片尺寸小的時(shí)候我們會(huì)選擇使用這種方式,不占用一次http的會(huì)話(huà)
- url:
- 因此我們可以采用發(fā)送ajax請(qǐng)求獲取圖片的編碼
- 將base64賦給img src即可
- 首先src的值可以是什么呢?
Q4: 對(duì)于請(qǐng)求一個(gè)圖片(文件)的情況,這些圖片和文件是以什么樣的模式在傳輸呢?為什么瀏覽器可以直接展示出圖片?
A4: 圖片和文件都是以二進(jìn)制流傳輸?shù)模ɑ蛘呖梢哉f(shuō)是文件對(duì)象的原始數(shù)據(jù)),瀏覽器可以直接將從服務(wù)器接受的二進(jìn)制流自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的文件和圖片
- Q5:客戶(hù)端接受服務(wù)器傳來(lái)的多類(lèi)型數(shù)據(jù)又是如何被瀏覽器識(shí)別并處理的呢?(瀏覽器怎么知道該如何處理二進(jìn)制數(shù)據(jù)流或者對(duì)象呢)
- A5: 首先需要知道MIME類(lèi)型:
- 是一種通知客戶(hù)端其接收文件的多樣性的機(jī)制
- 服務(wù)器會(huì)在response的Content-Type設(shè)置當(dāng)前response body的MIME type
- 當(dāng)瀏覽器接收到請(qǐng)求的時(shí)候會(huì)根據(jù)MIME type使用相應(yīng)的方式進(jìn)行對(duì)數(shù)據(jù)的處理
- 舉個(gè)栗子
- 在img 的src中設(shè)置一段請(qǐng)求靜態(tài)圖片的路徑
- express.js做服務(wù)器 res.sendFile
- 瀏覽器查看請(qǐng)求信息
- 再次查看請(qǐng)求的信息發(fā)現(xiàn)response headers的content-type是image/jpeg
- response body是一個(gè)二進(jìn)制數(shù)據(jù)流
- 因此瀏覽器通過(guò)識(shí)別出content-type是image/jpeg然后采用對(duì)圖片的處理機(jī)制去處理圖片并生成
- 和問(wèn)題相關(guān)
- 因此當(dāng)你使用ajax發(fā)送請(qǐng)求獲取圖片,可以獲取圖片的二進(jìn)制流
- 但是沒(méi)有方法處理這個(gè)二進(jìn)制流
- 所以沒(méi)有辦法展示圖片
- Q5: 客戶(hù)端該如何處理返回的二進(jìn)制流并將其轉(zhuǎn)換成base64編碼呢?
- A5:首先得讓服務(wù)器返回一個(gè)你知道如何轉(zhuǎn)換的二進(jìn)制流(讓返回的數(shù)據(jù)類(lèi)型已知可控)
- 對(duì)于不同的發(fā)送請(qǐng)求的方式,我們都有一個(gè)方法可以設(shè)置返回的數(shù)據(jù)類(lèi)型
- 舉個(gè)栗子:使用axios發(fā)送請(qǐng)求
axios.get('/****',{ responseType: 'blob' })
- 舉個(gè)栗子:使用axios發(fā)送請(qǐng)求
- 響應(yīng)的類(lèi)型(responseType的類(lèi)型):
- document: 靜態(tài)頁(yè)面
- blob:適用于讀取二進(jìn)制數(shù)據(jù),比如圖片文件
- arrayBuffer:也是用來(lái)處理處理二進(jìn)制數(shù)據(jù)但是是按照數(shù)組的方式處理二進(jìn)制數(shù)據(jù)
- json: 數(shù)據(jù),雖然和text差不多但是最大的優(yōu)點(diǎn)可以使用
JSON.parse將string變成對(duì)象 - text: 字符串
- 默認(rèn)值是json
- 這時(shí)候知道了返回的數(shù)據(jù)一定是一個(gè)blob類(lèi)型的數(shù)據(jù)就可以想辦法將blob數(shù)據(jù)讀成base64即可
- 對(duì)于不同的發(fā)送請(qǐng)求的方式,我們都有一個(gè)方法可以設(shè)置返回的數(shù)據(jù)類(lèi)型
- Q7:responseType的blob和arraybuffer之間的區(qū)別是什么呢?
- A7:都是二進(jìn)制數(shù)據(jù)的容器,那么對(duì)于這種二進(jìn)制流的數(shù)據(jù)我們?cè)撨x擇轉(zhuǎn)換成哪一種容器呢?
- blob:
- 代表原始的二進(jìn)制數(shù)據(jù)(js都不一定認(rèn)得)
- blob更偏重于整體操作(整個(gè)文件的二進(jìn)制流)
- arrayBuffer:
- js可以識(shí)別的二進(jìn)制數(shù)據(jù)
- 可以做流的切割,所有注重于對(duì)二進(jìn)制流中的字節(jié)進(jìn)行處理
- 因此在這里,我們更加偏重于對(duì)整個(gè)圖片二進(jìn)制流的處理因此選擇將response轉(zhuǎn)換成一個(gè)blob
- blob:
- Q8:如何將blob轉(zhuǎn)換成base64給src賦值呢?
- A8:FileReader可以將blob或者file類(lèi)型的數(shù)據(jù)裝換成其他類(lèi)型讀出
- FileReader
- 創(chuàng)建一個(gè)FileReader對(duì)象
new FileReader() - 然后調(diào)用fileReader.readAdDataUrl(blob)
- 將后端傳回的url直接轉(zhuǎn)成src的value
- 但是fileReader的方法都是異步的
- 因此需要定義一個(gè)回調(diào)函數(shù)
- fileReader.onLoad((e)=>{
//onload會(huì)在讀取成功的時(shí)候執(zhí)行
document.createElement('img').src = e.target.result;
})