成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

你知道前端對(duì)圖片的處理方式嗎?

helloworldcoding / 3040人閱讀

摘要:對(duì)于第二種存儲(chǔ)方式,我們前端需要將其二進(jìn)制流交由對(duì)象處理,然后通過(guò)的生成臨時(shí)賦值給屬性來(lái)顯示。當(dāng)后端返回特定的圖片二進(jìn)制流的時(shí)候,就像我第一里的情景再現(xiàn)說(shuō)的,前端用容器接收。

前言

作為前端工程師 de 我們,日常少不了會(huì)跟圖片打交道。在各大電商平臺(tái)工作的前端工程師們,感受可能會(huì)更加的明顯。

以下是我之前跟圖片打交道踩到的坑,跟大家分享一下經(jīng)驗(yàn)。

一、情景再現(xiàn)

用postman請(qǐng)求接口的時(shí)候,返回的是這個(gè)圖片(二進(jìn)制)

在chrome的network查看的時(shí)候,返回的也是這個(gè)圖片(二進(jìn)制)

可是,在debug打印的時(shí)候,返回的卻是亂碼

很明顯,數(shù)據(jù)的類(lèi)型已經(jīng)被改動(dòng)了。思考原因,唯一有可能改變數(shù)據(jù)類(lèi)型的地方是在axios。

我去翻看了一下axios的文檔,里面是這樣描述的

// `responseType` indicates the type of data that the server will respond with
// options are "arraybuffer", "blob", "document", "json", "text", "stream"
responseType: "json", // default

因此,亂碼出現(xiàn)的原因是因?yàn)椋?strong>axios默認(rèn)返回的是json文本形式,二進(jìn)制圖片數(shù)據(jù)被強(qiáng)制轉(zhuǎn)換成了json文本形式。

找到了原因,解決方案就好辦了。我們?cè)赼xios里面,responseType默認(rèn)返回?cái)?shù)據(jù)類(lèi)型是json,將其改為返回?cái)?shù)據(jù)類(lèi)型blob。

export function miniprogramQrcode (params) {
  return axios.post(
    env.MI_URL + "/XXXX/XXX/XXXX",
    params,
    // 將responseType的默認(rèn)json改為blob
    {
    responseType: "blob",
    emulateJSON: true
  }).then(res => {
    if (res.data) {
      return Promise.resolve(res.data)
    } else {
      throw res
    }
  }).catch(err => {
    return Promise.reject(err)
  })
}

接下來(lái)的問(wèn)題是,如何處理blob對(duì)象,將其顯示在前端頁(yè)面呢?

代碼如下:

createMiniQrcode (blob) {
  let img = document.createElement("img")
  img.onload = function (e) {
    // 元素的onload 事件觸發(fā)后將銷(xiāo)毀URL對(duì)象, 釋放內(nèi)存。
    window.URL.revokeObjectURL(img.src)
  }
  // 瀏覽器允許使用URL.createObjectURL()方法,針對(duì) Blob 對(duì)象生成一個(gè)臨時(shí) URL。
  // 這個(gè) URL 以blob://開(kāi)頭,表明對(duì)應(yīng)一個(gè) Blob 對(duì)象。
  img.src = window.URL.createObjectURL(blob)
  document.querySelector(".imgQrCode").appendChild(img)
}

是不是以為就這樣結(jié)束了? No, No, No. 了解如何解決問(wèn)題還不夠,還需要透過(guò)表象進(jìn)行發(fā)散思考。

二、 發(fā)散思考
一般來(lái)說(shuō),圖片在后端的存儲(chǔ)方式分為兩種:
其一:可以將圖片以獨(dú)立文件的形式存儲(chǔ)在服務(wù)器的指定文件夾中,再將路徑存入數(shù)據(jù)庫(kù)字段中;
其二:將圖片轉(zhuǎn)換成二進(jìn)制流,直接存儲(chǔ)到數(shù)據(jù)庫(kù)的 Image 類(lèi)型字段中.


對(duì)于第一種存儲(chǔ)方式,我們前端直接將存儲(chǔ)路徑賦值給src屬性即可輕松顯示。

對(duì)于第二種存儲(chǔ)方式,我們前端需要將其二進(jìn)制流交由blob對(duì)象處理,然后通過(guò)blob的API生成臨時(shí)URL賦值給src屬性來(lái)顯示。

兩種存儲(chǔ)方式都有對(duì)應(yīng)的解決方案,似乎已經(jīng)完美解決了關(guān)于圖片顯示的問(wèn)題。但是,我們的業(yè)務(wù)場(chǎng)景是多樣且多變的。有時(shí)候我們也會(huì)遇到這樣的場(chǎng)景,比如圖片拖拽上傳插件后,自動(dòng)返回給你了Blob對(duì)象,但不幸的是,你發(fā)現(xiàn)你又用了一個(gè)第三方的服務(wù)接口只接收 base64 格式的數(shù)據(jù),是否有點(diǎn)欲哭無(wú)淚?

那么,圖片的三種表現(xiàn)形式url、base64、blob,三者之間是否可以轉(zhuǎn)化以滿足需求呢?

1. url 轉(zhuǎn) base64

url to base64 的方法封裝

// 原理: 利用canvas.toDataURL的API轉(zhuǎn)化成base64

urlToBase64(url) {
  return new Promise ((resolve,reject) => {
      let image = new Image();
      image.onload = function() {
        let canvas = document.createElement("canvas");
        canvas.width = this.naturalWidth;
        canvas.height = this.naturalHeight;
        // 將圖片插入畫(huà)布并開(kāi)始繪制
        canvas.getContext("2d").drawImage(image, 0, 0);
        // result
        let result = canvas.toDataURL("image/png")
        resolve(result);
      };
      // CORS 策略,會(huì)存在跨域問(wèn)題https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
      image.setAttribute("crossOrigin","Anonymous");
      image.src = url;
      // 圖片加載失敗的錯(cuò)誤處理
      image.onerror = () => {
        reject(new Error("圖片流異常"));
    };
}

你可以這樣調(diào)用:

let imgUrL = `http://XXX.jpg`

this.getDataUri(imgUrL).then(res => {
  // 轉(zhuǎn)化后的base64圖片地址
  console.log("base64", res)
})
2. base64 轉(zhuǎn) blob

base64 to blob 的方法封裝

// 原理:利用URL.createObjectURL為blob對(duì)象創(chuàng)建臨時(shí)的URL

base64ToBlob ({b64data = "", contentType = "", sliceSize = 512} = {}) {
    return new Promise((resolve, reject) => {
      // 使用 atob() 方法將數(shù)據(jù)解碼
      let byteCharacters = atob(b64data);
      let byteArrays = [];
      for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        let slice = byteCharacters.slice(offset, offset + sliceSize);
        let byteNumbers = [];
        for (let i = 0; i < slice.length; i++) {
            byteNumbers.push(slice.charCodeAt(i));
        }
        // 8 位無(wú)符號(hào)整數(shù)值的類(lèi)型化數(shù)組。內(nèi)容將初始化為 0。
        // 如果無(wú)法分配請(qǐng)求數(shù)目的字節(jié),則將引發(fā)異常。
        byteArrays.push(new Uint8Array(byteNumbers));
      }
      let result = new Blob(byteArrays, {
        type: contentType
      })
      result = Object.assign(result,{
        // jartto: 這里一定要處理一下 URL.createObjectURL
        preview: URL.createObjectURL(result),
        name: `圖片示例.png`
      });
      resolve(result)
    })
 }

你可以這樣調(diào)用:

let base64 = base64.split(",")[1]

this.base64ToBlob({b64data: base64, contentType: "image/png"}).then(res => {
    // 轉(zhuǎn)后后的blob對(duì)象
    console.log("blob", res)
})


3. blob 轉(zhuǎn) base64

blob to base64 的方法封裝

// 原理:利用fileReader的readAsDataURL,將blob轉(zhuǎn)為base64

blobToBase64(blob) {
    return new Promise((resolve, reject) => {
      const fileReader = new FileReader();
      fileReader.onload = (e) => {
        resolve(e.target.result);
      };
      // readAsDataURL
      fileReader.readAsDataURL(blob);
      fileReader.onerror = () => {
        reject(new Error("文件流異常"));
      };
    });
}

你可以這樣調(diào)用:

this.blobToBase64(blob).then(res => {
    // 轉(zhuǎn)化后的base64
    console.log("base64", res)
})

ps: 以上方法是針對(duì)玩轉(zhuǎn)圖片流的優(yōu)化,感謝原作者。

在這里貼出url轉(zhuǎn)base64, base64與blob的相互轉(zhuǎn)化的demo,其它的會(huì)更新在這里,有興趣可以戳一下這里

三、圖片處理方式的歸納 1. 后端的圖片的存儲(chǔ)方式

在前面我們提到過(guò),圖片在后端的存儲(chǔ)有兩種方式,我們回顧一下:其一:可以將圖片以獨(dú)立文件的形式存儲(chǔ)在服務(wù)器的指定文件夾中,再將路徑存入數(shù)據(jù)庫(kù)字段中;其二:將圖片轉(zhuǎn)換成二進(jìn)制流,直接存儲(chǔ)到數(shù)據(jù)庫(kù)的 Image 類(lèi)型字段中;

那么這兩種存儲(chǔ)方式,哪種更優(yōu)呢?

據(jù)我了解,在互聯(lián)網(wǎng)環(huán)境中,大訪問(wèn)量,數(shù)據(jù)庫(kù)速度和性能方面很重要。一般在數(shù)據(jù)庫(kù)存儲(chǔ)圖片的做法比較少,更多的是將圖片路徑存儲(chǔ)在數(shù)據(jù)庫(kù)中,展示圖片的時(shí)候只需要連接磁盤(pán)路徑把圖片載入進(jìn)來(lái)即可。因?yàn)閳D片是屬于大字段。一張圖片可能1m到幾m。這樣的大字段數(shù)據(jù)會(huì)加重?cái)?shù)據(jù)庫(kù)的負(fù)擔(dān),拖慢數(shù)據(jù)庫(kù)。在大并發(fā)訪問(wèn)的情況下很重要。這是一個(gè)經(jīng)驗(yàn)。去看看dba對(duì)數(shù)據(jù)庫(kù)性能調(diào)優(yōu)方面的分析都能得到這個(gè)答案的:就是圖片不要存儲(chǔ)在數(shù)據(jù)庫(kù)中。

因此,如果你司的后端小哥哥經(jīng)常將圖片以二進(jìn)制的形式存儲(chǔ)到數(shù)據(jù)庫(kù)然后返回給你對(duì)接,你應(yīng)該知道如何去dui他了吧(滑稽臉)。

更多關(guān)于圖片或者文件在數(shù)據(jù)庫(kù)的存儲(chǔ)方式的歸納請(qǐng)戳這里

2. 前端的圖片的顯示方式

對(duì)于前端來(lái)說(shuō):
圖片在前端顯示有三種方式:url、base64、blob

三種顯示方式,哪種更優(yōu)雅呢?

url: 一般來(lái)說(shuō),圖片的顯示還是建議使用url的方式比較好。如果后端傳過(guò)來(lái)的字段是圖片路徑的話。

base64:如果圖片較大,圖片的色彩層次比較豐富,則不適合使用這種方式,因?yàn)槠銪ase64編碼后的字符串非常大,會(huì)明顯增大HTML頁(yè)面,影響加載速度。
如果圖片像loading或者表格線這樣的,大小極小,但又占據(jù)了一次HTTP請(qǐng)求,而很多地方都會(huì)使用。則非常適用“base64:URL圖片”技術(shù)進(jìn)行優(yōu)化了!詳細(xì)的張?chǎng)涡竦腄emo演示,請(qǐng)戳這里一下。

blob: 當(dāng)后端返回特定的圖片二進(jìn)制流的時(shí)候,就像我第一part里的情景再現(xiàn)說(shuō)的,前端用blob容器接收。圖片用blob展示會(huì)比較好。

四、感想

付出,記錄,總結(jié)。在項(xiàng)目中遇到的問(wèn)題我都會(huì)一點(diǎn)一滴的記錄整理下來(lái)。我相信,這些都是一片一片散落的枝葉,隨著項(xiàng)目經(jīng)驗(yàn)的增多,這些枝葉最終一定能夠成長(zhǎng)為一棵參天大樹(shù)。

文中的觀點(diǎn)受限于本人當(dāng)前的技術(shù)水平,難免會(huì)有講錯(cuò)的地方,歡迎評(píng)論區(qū)留言交流指正。

隨著技術(shù)水平的提升,文章會(huì)不定期的迭代而優(yōu)化~你可以通過(guò)下面的方式聯(lián)系到我。

關(guān)于我

我的github主頁(yè)(點(diǎn)擊進(jìn)入)

我的掘金主頁(yè)(點(diǎn)擊進(jìn)入)

我的SG主頁(yè)(點(diǎn)擊進(jìn)入)

我的簡(jiǎn)書(shū)主頁(yè)(點(diǎn)擊進(jìn)入)

我的公眾號(hào)(點(diǎn)擊進(jìn)入或者掃描下方二維碼)

文章回顧:

2018年的文章寫(xiě)作進(jìn)度表

參考資料:

ArrayBuffer對(duì)象,Blob對(duì)象

axios-api文檔

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102109.html

相關(guān)文章

  • 知道前端對(duì)圖片處理方式?

    摘要:對(duì)于第二種存儲(chǔ)方式,我們前端需要將其二進(jìn)制流交由對(duì)象處理,然后通過(guò)的生成臨時(shí)賦值給屬性來(lái)顯示。當(dāng)后端返回特定的圖片二進(jìn)制流的時(shí)候,就像我第一里的情景再現(xiàn)說(shuō)的,前端用容器接收。 前言 作為前端工程師 de 我們,日常少不了會(huì)跟圖片打交道。在各大電商平臺(tái)工作的前端工程師們,感受可能會(huì)更加的明顯。 以下是我之前跟圖片打交道踩到的坑,跟大家分享一下經(jīng)驗(yàn)。 一、情景再現(xiàn) 用postman請(qǐng)求接口...

    LiuRhoRamen 評(píng)論0 收藏0
  • 知道前端對(duì)圖片處理方式?

    摘要:對(duì)于第二種存儲(chǔ)方式,我們前端需要將其二進(jìn)制流交由對(duì)象處理,然后通過(guò)的生成臨時(shí)賦值給屬性來(lái)顯示。當(dāng)后端返回特定的圖片二進(jìn)制流的時(shí)候,就像我第一里的情景再現(xiàn)說(shuō)的,前端用容器接收。 前言 作為前端工程師 de 我們,日常少不了會(huì)跟圖片打交道。在各大電商平臺(tái)工作的前端工程師們,感受可能會(huì)更加的明顯。 以下是我之前跟圖片打交道踩到的坑,跟大家分享一下經(jīng)驗(yàn)。 一、情景再現(xiàn) 用postman請(qǐng)求接口...

    Zachary 評(píng)論0 收藏0
  • 前端面試每日3+1(周匯總2019.08.11)

    摘要:前端面試每日題,以面試題來(lái)驅(qū)動(dòng)學(xué)習(xí),每天進(jìn)步一點(diǎn)讓努力成為一種習(xí)慣,讓奮斗成為一種享受相信堅(jiān)持的力量項(xiàng)目地址推薦歡迎跟一起折騰前端,系統(tǒng)整理前端知識(shí),目前正在折騰,打算打通算法與數(shù)據(jù)結(jié)構(gòu)的任督二脈。 《論語(yǔ)》,曾子曰:吾日三省吾身(我每天多次反省自己)。 前端面試每日3+1題,以面試題來(lái)驅(qū)動(dòng)學(xué)習(xí),每天進(jìn)步一點(diǎn)! 讓努力成為一種習(xí)慣,讓奮斗成為一種享受!相信 堅(jiān)持 的力量?。?! 項(xiàng)目...

    Baoyuan 評(píng)論0 收藏0
  • 前端面試每日3+1(周匯總2019.08.11)

    摘要:前端面試每日題,以面試題來(lái)驅(qū)動(dòng)學(xué)習(xí),每天進(jìn)步一點(diǎn)讓努力成為一種習(xí)慣,讓奮斗成為一種享受相信堅(jiān)持的力量項(xiàng)目地址推薦歡迎跟一起折騰前端,系統(tǒng)整理前端知識(shí),目前正在折騰,打算打通算法與數(shù)據(jù)結(jié)構(gòu)的任督二脈。 《論語(yǔ)》,曾子曰:吾日三省吾身(我每天多次反省自己)。 前端面試每日3+1題,以面試題來(lái)驅(qū)動(dòng)學(xué)習(xí),每天進(jìn)步一點(diǎn)! 讓努力成為一種習(xí)慣,讓奮斗成為一種享受!相信 堅(jiān)持 的力量?。?! 項(xiàng)目...

    馬永翠 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<