JS 判断文件是否为图片,原理就是检测文件的 Magic Number
对 JPEG、GIF、PNG 的 magic number 的检测如下:
// 使用magicNumber判断图片类型
// 一句话形容magic Number就是:文件的唯一标识
// 一些比较常见的图片及其magic number:
// 图片类型 扩展名 magic number(以其开头)
// 对 JPEG、GIF、PNG 的 magic number 的检测如下:
const isImage = (buf) => {
const pngMagic = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
const jpeg_jfif = [0x4a, 0x46, 0x49, 0x46];
const jpeg_exif = [0x45, 0x78, 0x69, 0x66];
const jpegMagic = [0xFF, 0xD8, 0xFF, 0xE0];
const gifMagic0 = [0x47, 0x49, 0x46, 0x38, 0x37, 0x61];
const getGifMagic1 = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61];
// 6 bytes
const isGif = data => (arrayEquals(data, gifMagic0) || arrayEquals(data, getGifMagic1))
// 4 bytes
const isJpeg = data => (arrayEquals(data, jpegMagic) || arrayEquals(data, jpeg_jfif) || arrayEquals(data, jpeg_exif))
// 8 bytes
const isPng = data => arrayEquals(data, pngMagic)
const arraycopy = (src, index, dist, distIndex, size) => {
for (let i = 0; i < size; i++) {
dist[distIndex + i] = src[index + i]
}
}
const arrayEquals = (arr1, arr2) => {
if (!arr1 || !arr2) {
return false
}
if (arr1 instanceof Array && arr2 instanceof Array) {
if (arr1.length != arr2.length) {
return false
}
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false
}
}
return true
}
return false;
}
if (!buf || buf.length < 8) {
return null;
}
let bytes = [];
arraycopy(buf, 0, bytes, 0, 6);
if (isGif(bytes)) {
return "image/gif";
}
bytes = [];
arraycopy(buf, 6, bytes, 0, 4);
if (isJpeg(bytes)) {
return "image/jpeg";
}
bytes = [];
arraycopy(buf, 0, bytes, 0, 8);
if (isPng(bytes)) {
return "image/png";
}
return null;
}
const checkImage = file => {
if (!file || !(file instanceof File)) throw '文件不存在'
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = (evt) => {
//取前11Bytes转换成Uint8Array
let fileBuf = new Uint8Array(evt.target.result.slice(0, 11));
//调用之前的方法判断是不是图片
//如果不是返回null,否则返回mimeType
let mime = isImage(fileBuf);
resolve(mime)
};
reader.onerror = ev => {
resolve(null)
}
//读取文件为ArrayBuffer
reader.readAsArrayBuffer(file);
})
}
// 获取图片文件的信息
const getImgFileInfo = file => {
if (!file || !(file instanceof File)) throw '文件不存在'
return new Promise((resolve, reject) => {
const url = window.URL || window.webkitURL
// 手动创建一个Image对象
const img = new Image()
// 创建Image的对象的url
img.src = url.createObjectURL(file)
// onload 加载完成后触发
img.onload = () => resolve({ width: img.width, height: img.height })
// onload 加载完成后触发
img.onload = () => resolve({ success: true, width: img.width, height: img.height })
// onerror
img.onerror = () => resolve({ success: false })
})
}
在 HTML 中使用如下:
function handleFileSelect(evt) {
var files = evt.target.files;
if (files[0]) {
checkImage(files[0]).then(isImg => {
if (isImg) {
// 是图片文件 ....
} else {
// 不是图片文件 ....
}
})
}
}