圖片上傳和預(yù)覽踩坑

功能需求

  • 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
    • file.type: 指的是文件發(fā)送的類(lèi)型
      • 例子:'image/jpeg', 'image/jpg', 'image/png', 'image/bmp'
  • 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à)
    • 因此我們可以采用發(fā)送ajax請(qǐng)求獲取圖片的編碼
    • 將base64賦給img 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'
        })
        
    • 響應(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即可

  • 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

  • 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;
      })
發(fā)現(xiàn)js中文件的處理部分還是很不熟悉js文件和二進(jìn)制流的處理
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容