exif.getdata() 对 file 对象无效,因它仅支持已加载的 元素,依赖 src 或 canvas,而 file 无 src 且未渲染;正确方式是用 filereader.readasarraybuffer() 配合 exif.readfrombinaryfile() 或更优的 exifreader。

不能直接用 EXIF.getData() 传 <input type="file"> 的 files[0] ——它只接受 <img> 元素,且底层依赖 HTTP 请求或 Canvas 绘制,而 File 对象既不是 URL 也不是已加载图像。
为什么 EXIF.getData() 对 File 对象完全无效
exif-js(包括维护分支 exif2)的 EXIF.getData() 函数设计目标是解析已渲染的 <img> 标签:它会尝试读取 this.src 并发起新请求(触发 CORS 限制),或用 Canvas 绘制后读像素(触发 SecurityError)。File 对象没有 src,也不在 DOM 中,所以传进去只会静默失败、回调不执行、无报错。
- 传
input.files[0]进EXIF.getData()→ 回调函数根本不会被调用 - 试图对
File调用EXIF.getAllTags()→ 报TypeError: Cannot read property 'length' of undefined或类似错误 - 哪怕你手动创建
new Image()并img.src = URL.createObjectURL(file),仍需等img.onload后再调EXIF.getData(),否则naturalWidth为 0,EXIF 解析失败
正确做法:用 FileReader + exif-js 的 EXIF.readFromBinaryFile()
exif-js 提供了底层方法 EXIF.readFromBinaryFile(),它接收 ArrayBuffer,正好匹配 FileReader.readAsArrayBuffer() 的输出。这是唯一能从 File 对象安全提取 EXIF 的标准路径。
- 必须用
readAsArrayBuffer(),不能用readAsDataURL()或readAsText() -
EXIF.readFromBinaryFile()返回的是原始解析结果对象,不是通过回调;错误会抛出异常,需try/catch - 该方法不依赖 CORS、不依赖 Canvas、不依赖网络,纯二进制解析,适合上传前预览场景
示例代码:
document.getElementById('fileInput').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file || !file.type.match('image/jpeg')) return;
const reader = new FileReader();
reader.onload = function() {
try {
const exifData = EXIF.readFromBinaryFile(this.result); // this.result 是 ArrayBuffer
const make = EXIF.getTag(exifData, 'Make');
const model = EXIF.getTag(exifData, 'Model');
console.log('相机:', make, model);
} catch (err) {
console.warn('EXIF 解析失败:', err.message);
}
};
reader.readAsArrayBuffer(file);
});
更稳的选择:换用 piexifjs 或 exifreader
原生 exif-js 的 readFromBinaryFile() 虽可用,但已多年未更新,对非标准 JPEG(如手机直出带私有 IFD 的图)兼容性差,GPS 解析逻辑也简陋。生产环境建议切换:
-
piexifjs:支持读写 EXIF,API 清晰,piexif.load(arraybuffer)直接返回结构化对象,GPS 坐标自动转为十进制度 -
exifreader(推荐):TypeScript 编写,轻量、无依赖、错误容忍强,ExifReader.load(arraybuffer)返回 Promise,支持 WebP(有限)、HEIC(需额外解码) - 注意:
exifreader不解析缩略图(Thumbnail IFD),若需,得手动处理tags.Thumbnail
真正容易被忽略的一点:很多手机拍的图默认不开 GPS,或者用户在系统设置里关了定位写入,这时候连 GPSInfo 字段都不会存在——别一上来就查 GPSLatitude,先 if ('GPSInfo' in tags) 再取值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











