如何用JavaScript准确识别图片的真实文件类型?
如何用JavaScript正确识别图片的真实文件类型(而非URL后缀)
通过URL后缀判断图片类型不可靠,很多场景下服务器会返回与URL后缀不符的实际文件(比如示例中的URL后缀是jpg,但实际是webp)。原代码通过url.pathname.split('.').pop()获取扩展名的方式会导致识别错误。
尝试使用file-type库时出现两个错误:
- CDN地址错误导致404:
https://cdn.jsdelivr.net/npm/file-type/dist/index.umd.js路径不存在 - 库未正确加载,导致
window.fileType为undefined,进而报错Cannot read properties of undefined (reading 'fromBuffer')
错误原因
file-type的UMD包路径在不同版本中有所变化,旧路径已失效。此外,依赖第三方库可能存在版本兼容或CDN不稳定的问题。
方案1:修复file-type库的使用
首先确认file-type的正确UMD包路径,以v18版本为例,正确的CDN地址是https://cdn.jsdelivr.net/npm/file-type@18/dist/bundle.umd.js。以下是修复后的完整代码:
<!DOCTYPE html> <html> <head> <title>Identify Image File Type</title> </head> <body> <img id="image"> <script src="https://cdn.jsdelivr.net/npm/file-type@18/dist/bundle.umd.js"></script> <script> const imageUrl = 'https://s.alicdn.com/@sc04/kf/H7c1b38f112d044889f7b2c5a2ab914ac3.jpg_100x100xz.jpg'; fetch(imageUrl) .then(response => response.arrayBuffer()) .then(buffer => { const fileType = window.fileType.fromBuffer(new Uint8Array(buffer)); if (!fileType) { console.log('无法识别文件类型'); return; } console.log(`真实文件类型是 ${fileType.ext}`); const image = document.getElementById('image'); image.addEventListener('load', () => { const width = image.naturalWidth; const height = image.naturalHeight; console.log(`图片尺寸:${width}x${height}`); }); image.addEventListener('error', () => { console.log('图片加载失败'); }); const objectUrl = window.URL.createObjectURL(new Blob([buffer], { type: fileType.mime })); image.src = objectUrl; }) .catch(error => { console.log(`请求图片出错:${error.message}`); }); </script> </body> </html>
方案2:原生JS检测文件头(无需第三方库)
直接读取图片文件的前几个字节(魔术数字)来判断真实类型,更稳定且无依赖。webp的文件头特征是:前4字节为RIFF(ASCII码:0x52, 0x49, 0x46, 0x46),第9-12字节为WEBP(ASCII码:0x57, 0x45, 0x42, 0x50)。以下是实现代码:
<!DOCTYPE html> <html> <head> <title>Identify Image File Type</title> </head> <body> <img id="image"> <script> const imageUrl = 'https://s.alicdn.com/@sc04/kf/H7c1b38f112d044889f7b2c5a2ab914ac3.jpg_100x100xz.jpg'; // 检测webp文件头 function isWebp(buffer) { const uint8 = new Uint8Array(buffer); // 检查RIFF标记 const riff = uint8.slice(0,4).every((byte, index) => byte === 'RIFF'.charCodeAt(index)); if (!riff) return false; // 检查WEBP标记(第9-12字节) const webp = uint8.slice(8,12).every((byte, index) => byte === 'WEBP'.charCodeAt(index)); return webp; } fetch(imageUrl) .then(response => response.arrayBuffer()) .then(buffer => { let fileType = 'unknown'; if (isWebp(buffer)) { fileType = 'webp'; } // 可扩展其他类型检测,比如jpg、png等 console.log(`真实文件类型是 ${fileType}`); const image = document.getElementById('image'); image.addEventListener('load', () => { console.log(`图片尺寸:${image.naturalWidth}x${image.naturalHeight}`); }); image.addEventListener('error', () => { console.log('图片加载失败'); }); const objectUrl = window.URL.createObjectURL(new Blob([buffer])); image.src = objectUrl; }) .catch(error => { console.log(`请求图片出错:${error.message}`); }); </script> </body> </html>
说明:方案2可以根据需要扩展对其他图片格式的检测,比如jpg的文件头是FF D8 FF,png是89 50 4E 47 0D 0A 1A 0A,这样无需依赖任何第三方库即可准确识别真实文件类型。
内容的提问来源于stack exchange,提问作者Waleed Farrukh
相关产品推荐
相关产品推荐

