正常状况下,文件都是有后缀名的,例如:坤坤运球.gif, 坤坤跳舞.avihtml
可是也有无后缀名的文件。尝试着把 坤坤运球.gif
的文件后缀去掉,而后用图片查看器打开该文件,一样能看到坤坤精湛的球技。npm
这说明,改变文件的后缀名,并不会影响文件自己的内容。同时也说明,文件的数据中,有东西可以标识出文件的类型。url
说以上那么多,实际上是想引出 Magic Number) 的概念。简单的来讲,Magic Number 由文件数据中前几个字节组成, 同一类型的文件这几个字节都是同样的,故而能够标识出一个文件的类型。因为这串数字从字面上来看是没法理解的,故而称之为 Magic Number,原名叫作:File Signatures(文件签名)。.net
首先这里有一个文件url
,告诉你这是一个音频文件,你能看出它是什么类型的音频文件吗?prototype
const url = 'https://0345-1400187352-1256635546.cos.ap-shanghai.myqcloud.com/rychou/e3801cfc517873a5a5471241e1da1869'
很显然是看不出来的,由于这个文件没有后缀。接下来看看如何利用 Magic Number
来判断这个音频文件的类型。code
能够参考 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 Buffer
ssl
/** * 加载文件 * @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 进制字符串 * @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,供你们参考使用。