「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战
vue3
出来那么久了,总得搞点有意思的东西,一时兴起就搞了小项目玩一玩,项目地址点这里,该项目是用 node + egg.js + vue3 + ts + element + vite, 数据库用的是 cloud.mongodb,项目还在继续开发的过程中,也欢迎大家 star
, 有想法的话同学可以互相交流一下。
今天就拿其中的图片上传做一个分享,图片上传用的是16进制去判断图片类型的 有同学就会疑惑了,在上传图片的时候,其实我们就可以拿到图片的后缀名,即 .jpg
,.png
等等格式的文件,为什么还要多此一举用16进制去判断呢?文件的后缀名用户是可以手动修改的,修改了之后判断可能就不准确了,这个16进制是为了做一次更准确的验证。
vscode 插件
既然要用 16 进制,那我们怎么查看图片的编码呢? vscode 给我们提供了一个很好的插件 hexdump for VSCode,右击图片选择 Show Hexdump
查看不同的文件编码
FileReader
我们通过 FileReader 来实现一个转码
FileReader MDN 返回一个新构造的FileReader。
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
reader.result
是一个字符传,把他转为数组- 转为 ASCII 码
- 转为 16 进制的字符串
- 字符串填充 padStart 在原字符串开头填充指定的填充字符串直到目标长度所形成的新字符串。
const blobToString = (blob) => {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = function () {
const res = reader.result
.split('')
.map((v) => v.charCodeAt()) // 转码
.map((v) => v.toString(16).toUpperCase()) // 转为 16 进制
.map((v) => v.padStart(2, '0')) // 字符串填充
.join('')
resolve(res)
}
reader.readAsBinaryString(blob)
})
}
复制代码
readAsBinaryString: 开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.
判断是否是.gif
取前面 6 位 16 进制
const res = await blobToString(file.slice(0, 6))
const isGif = res == '47 49 46 38 39 61' || res == '47 49 46 38 37 61'
复制代码
判断是否是.png
取前面 8 位 16 进制
const res = await blobToString(file.slice(0, 8))
const isPng = res == '89 50 4E 47 0D 0A 1A 0A'
复制代码
判断是否是.jpg
取首尾各 2 位
const start = await blobToString(file.slice(0, 2))
const tail = await blobToString(file.slice(-2, len))
const isJpg = start == 'FF D8' && tail == 'FF D9'
复制代码