無後綴文件的類型檢測

正常狀況下,文件都是有後綴名的,例如:坤坤運球.gif, 坤坤跳舞.avihtml

可是也有無後綴名的文件。嘗試着把 坤坤運球.gif 的文件後綴去掉,而後用圖片查看器打開該文件,一樣能看到坤坤精湛的球技。npm

這說明,改變文件的後綴名,並不會影響文件自己的內容。同時也說明,文件的數據中,有東西可以標識出文件的類型。url

說以上那麼多,實際上是想引出 Magic Number) 的概念。簡單的來講,Magic Number 由文件數據中前幾個字節組成, 同一類型的文件這幾個字節都是同樣的,故而能夠標識出一個文件的類型。因爲這串數字從字面上來看是沒法理解的,故而稱之爲 Magic Number,原名叫作:File Signatures(文件簽名)。.net

利用 Magic Number 判斷文件類型

首先這裏有一個文件url,告訴你這是一個音頻文件,你能看出它是什麼類型的音頻文件嗎?prototype

const url = 'https://0345-1400187352-1256635546.cos.ap-shanghai.myqcloud.com/rychou/e3801cfc517873a5a5471241e1da1869'

很顯然是看不出來的,由於這個文件沒有後綴。接下來看看如何利用 Magic Number 來判斷這個音頻文件的類型。code

找到不一樣類型文件的 Magic Number

能夠參考 Magic Number Table 中的數據,找到不一樣類型文件的 Magic Number。htm

例如:搜索 mp3, 找到 mp3 文件類型的 Magic Number 爲: 49 44 33。注意這是個 16 進制數。圖片

// 常見的音頻文件的 magic number
const hexMap = {
 '494433': 'mp3',
 '664c614300000022': 'flac',
 '2321414d52': 'amr',
 'fff1': 'aac',
 'fff9': 'aac',
 '4f67675300020000000000000000': 'oga',
 '52494646xxxxxxxx57415645666d7420': 'wav',
 '3026b2758e66cf11a6d900aa0062ce6c': 'wma'
}

// 利用 16 進制字符串判斷類型
const isAAC = hex => !!hexMap[hex.slice(0, 4)]
const isMP3 = hex => !!hexMap[hex.slice(0, 6)]
const isAMR = hex => !!hexMap[hex.slice(0, 10)]
const isFLAC = hex => !!hexMap[hex.slice(0, 16)]
const isWAV = hex => !!hexMap[hex.slice(0, 32)]
const isWMA = hex => !!hexMap[hex.slice(0, 32)]
const isOGA = hex => !!hexMap[hex.slice(0, 28)]

找到了文件的 Magic Number,要判斷文件的類型就很簡單了。ip

### 請求獲取文件數據,並轉成 Array Bufferssl

/**
* 加載文件
* @param {string} url - audio file url
* @returns {Promise}
*/
function loadFile(url) {
 return new Promise((resolve, reject) => {
   const xhr = new XMLHttpRequest()
   xhr.onreadystatechange = function() {
     if (xhr.readyState === 4) {
       resolve(xhr)
     }
   }
   xhr.onerror = reject
   xhr.open('GET', url, true)
   xhr.responseType = 'arraybuffer'
   xhr.send('')
 })
}

buffer 轉 16 進制字符串

/**
 * buffer 轉 16 進制字符串
 * @param {ArrayBuffer} buffer
 * @returns
 */
function buf2hex(buffer) {
  // buffer is an ArrayBuffer
  return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('')
}

判斷類型

function getAudioType(url) {
  return loadFile(url).then(xhr => {
      const hex = buf2hex(buffer)
      if (isAAC(hex)) {
        return 'aac'
      } else if (isAMR(hex)) {
        return 'amr'
      } else if (isMP3(hex)) {
        return 'mp3'
      } else if (isFLAC(hex)) {
        return 'flac'
      } else if (isWAV(hex)) {
        return 'wav'
      } else if (isWMA(hex)) {
        return 'wma'
      } else if (isOGA(hex)) {
        return 'oga'
      } else {
        return false
      }
  })
}

通過以上一系列操做,最終能夠得出,該音頻文件是個 aac 類型的文件。

總結

不僅是音頻文件,全部文件類型均可以經過 Magic Number 來判斷文件類型,原理都是同樣的,只要能找到這個數字,就能判斷類型,無論有無文件後綴。

最後,根據以上的方法,以及最近項目中的實際需求,寫了一個用於判斷音頻文件類型的 npm 包 —— audio-type-detect,供你們參考使用。

相關文章
相關標籤/搜索