url、base64、blob,三者之間的轉(zhuǎn)化

對于vue項(xiàng)目,我們使用axiso來發(fā)送請求,如果傳遞二進(jìn)制圖片時出現(xiàn)亂碼,這個是什么問題?

axios 默認(rèn)返回的是 json 文本形式,二進(jìn)制圖片數(shù)據(jù)被強(qiáng)制轉(zhuǎn)換成了 json 文本形式。
解決方案:
我們在 axios 里面,responseType 默認(rèn)返回?cái)?shù)據(jù)類型是 json,將其改為返回?cái)?shù)據(jù)類型 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)
  })
}

接下來,就是處理blob對象,將其顯示在前端頁面

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

圖片在后端的存儲方式有哪些?

一般來說,圖片在后端的存儲方式分為兩種
1)可以將圖片以獨(dú)立文件的形式存儲在服務(wù)器的指定文件夾中,再將路徑存入數(shù)據(jù)庫字段中;
(2)將圖片轉(zhuǎn)換成二進(jìn)制流,直接存儲到數(shù)據(jù)庫的 Image 類型字段中.

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

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

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

image.png

1. url 轉(zhuǎn) 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;
            // 將圖片插入畫布并開始繪制
            canvas.getContext('2d').drawImage(image, 0, 0);
            // result
            let result = canvas.toDataURL('image/png')
            resolve(result);
          };
          // CORS 策略,會存在跨域問題https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
          image.setAttribute("crossOrigin",'Anonymous');
          image.src = url;
          // 圖片加載失敗的錯誤處理
          image.onerror = () => {
            reject(new Error('圖片流異常'));
        };
    }

調(diào)用

let imgUrL = `http://XXX.jpg`
    
    this.getDataUri(imgUrL).then(res => {
      // 轉(zhuǎn)化后的base64圖片地址
      console.log('base64', res)
    })

base64 轉(zhuǎn) blob

// 原理:利用URL.createObjectURL為blob對象創(chuàng)建臨時的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 位無符號整數(shù)值的類型化數(shù)組。內(nèi)容將初始化為 0。
          // 如果無法分配請求數(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對象
        console.log('blob', res)
    })

blob 轉(zhuǎn) 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)
    })

//base64 轉(zhuǎn)成 File 對象

//base64 轉(zhuǎn)成 File 對象
function base64toFile(dataurl, filename) {//將base64轉(zhuǎn)換為文件
                var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
                  bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
                while(n--){
                  u8arr[n] = bstr.charCodeAt(n);
                }
                return new File([u8arr], filename, {type:mime});
              }

在互聯(lián)網(wǎng)環(huán)境中,大訪問量,數(shù)據(jù)庫速度和性能方面很重要。一般在數(shù)據(jù)庫存儲圖片的做法比較少,更多的是將圖片路徑存儲在數(shù)據(jù)庫中,展示圖片的時候只需要連接磁盤路徑把圖片載入進(jìn)來即可。因?yàn)閳D片是屬于大字段。一張圖片可能1m到幾m。這樣的大字段數(shù)據(jù)會加重?cái)?shù)據(jù)庫的負(fù)擔(dān),拖慢數(shù)據(jù)庫。在大并發(fā)訪問的情況下很重要。這是一個經(jīng)驗(yàn)。去看看dba對數(shù)據(jù)庫性能調(diào)優(yōu)方面的分析都能得到這個答案的:就是圖片不要存儲在數(shù)據(jù)庫中。
————————————————
版權(quán)聲明:本文為CSDN博主「馬優(yōu)晨」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_24147051/article/details/88087665

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。