const patternMask = [
{
name: 'image/x-icon',
mask: [0xff, 0xff, 0xff, 0xff],
byte: [0x00, 0x00, 0x01, 0x00],
},
{
name: 'image/x-icon',
mask: [0xff, 0xff, 0xff, 0xff],
byte: [0x00, 0x00, 0x02, 0x00],
},
{
name: 'image/bmp',
mask: [0xff, 0xff],
byte: [0x42, 0x4d],
},
{
name: 'image/gif',
mask: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
byte: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61],
},
{
name: 'image/gif',
mask: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
byte: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61],
},
{
name: 'image/webp',
mask: [0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
byte: [0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50],
},
{
name: 'image/png',
mask: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
byte: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
},
{
name: 'image/jpeg',
mask: [0xff, 0xff, 0xff],
byte: [0xff, 0xd8, 0xff],
},
]
export function isEmptyObj(data) {
if (!data) return true
return JSON.stringify(data) === '{}'
}
export function createId() {
return Math.random()
.toString(36)
.substring(2)
}
* 检测是否是动图
* 主要针对 Gif 和 Webp 两种格式
*/
export async function checkIsAnimated({ file, fileUrl, fileType }) {
if (!file || !(file instanceof File)) {
console.error('isAnimated param check fail: param expected to be File object')
return false
}
if (fileType !== 'image/webp' && fileType !== 'image/gif') {
return false
}
if (fileType === 'image/webp') {
return new Promise(resolve => {
const request = new XMLHttpRequest()
request.open('GET', fileUrl, true)
request.addEventListener('load', () => {
resolve(request.response.indexOf('ANMF') !== -1)
})
request.send()
})
}
if (fileType === 'image/gif') {
return new Promise(resolve => {
const request = new XMLHttpRequest()
request.open('GET', fileUrl, true)
request.responseType = 'arraybuffer'
request.addEventListener('load', () => {
const arr = new Uint8Array(request.response)
if (arr[0] !== 0x47 || arr[1] !== 0x49 || arr[2] !== 0x46 || arr[3] !== 0x38) {
resolve(false)
return
}
let frames = 0
for (let i = 0, len = arr.length - 9; i < len && frames < 2; ++i) {
if (
arr[i] === 0x00
&& arr[i + 1] === 0x21
&& arr[i + 2] === 0xf9
&& arr[i + 3] === 0x04
&& arr[i + 8] === 0x00
&& (arr[i + 9] === 0x2c || arr[i + 9] === 0x21)
) {
frames++
}
}
resolve(frames > 1)
})
request.send()
})
}
}
* 检测文件类型
* 使用文件编码进行检测
* 支持模式参看: patternMask 定义
*/
export async function getFileType(file) {
if (!(file instanceof File)) {
return 'unknown'
}
return new Promise(resolve => {
const fileReader = new FileReader()
fileReader.onloadend = e => {
const header = new Uint8Array(e.target.result).slice(0, 20)
let type = 'unknown'
const index = patternMask.findIndex(item => {
return item.mask.every((subItem, subI) => {
return (subItem & (header[subI] ^ item.byte[subI])) === 0
})
})
if (index >= 0) {
type = patternMask[index].name
}
resolve(type)
}
fileReader.readAsArrayBuffer(file)
})
}