magic Number
起因:做项目时需要对图片的类型进行判断,但是有些图片后缀名是jpg,但是里面的内容是png的形式;里面是gif,后缀确实显示jpg等等…,为了能够准确的拿捏图片真正的数据格式,我们可以使用magic Number
来对图片的二进制数据进行判断
一句话形容magic Number就是:文件的唯一标识
常见的图片
一些比较常见的图片及其magic number:
图片类型 | 扩展名 | magic number(以其开头) |
---|---|---|
GIF format | .gif | 47 49 46 38 |
JPEG File Interchange Format | .jpg | ff d8 ff e0 |
PNG format | .png | 89 50 4e 47 |
PDF format | 25 50 44 46 | |
pkzip format | .zip | 50 4b 03 04 |
借助ArrayBuffer,我们可以得到图片的二进制数据,在对其magic number 进行对比,即可确定图片|文件的格式
判断图片的案例
code
<input type="file" class="ipt">
<script>
!(function () {
const ipt = document.querySelector('.ipt')
ipt.addEventListener('change', () => {
// 拿到图片
const file = ipt.files[0]
// 创建文件读取对象
const fr = new FileReader()
// 添加load事件
fr.addEventListener('load', () => {
const arrBuffer = fr.result
for (let ft in fileType) {
if (fileType[ft] instanceof Function) {
fileType[ft](arrBuffer) ? alert(ft) : null
}
}
})
// 读取图片
fr.readAsArrayBuffer(file) // 读取file文件
const hex2string = (byte) => {
// 3 => 03 5 => 05
return byte.toString(16).padStart(2, '0')
}
// 工厂函数
const getFileType = (hex) => {
return (arrayBuffer) => {
const int8Array = new Uint8Array(arrayBuffer)
const data = int8Array.slice(0, 4)
const hexArr = hex.split(/\s+/)
let flag = true
data.map((item, index) => {
if (hex2string(item.toString(16)) !== hexArr[index]) {
flag = false
}
})
return flag
}
}
const fileType = {
jpeg: getFileType('ff d8 ff e0'),
gif: getFileType('47 49 46 38'),
png: getFileType('89 50 4e 47'),
pdf: getFileType('25 50 44 46'),
zip: getFileType('50 4b 03 04')
}
})
})()
</script>