ReactJS中调整图片大小并保留元数据(EXIF)的实现方案
解决React图片压缩后保留EXIF元数据的方案
react-image-file-resizer这类库在压缩时会直接丢弃原图片的EXIF数据,要实现压缩+保留元数据,得拆成两步处理:先提取原文件的EXIF,再把它注入到压缩后的图片里。
具体实现步骤
1. 安装依赖
用到三个实用库:
exifr:轻量浏览器端EXIF提取工具,能精准获取拍摄时间、GPS等信息browser-image-compression:比react-image-file-resizer更灵活的压缩工具piexifjs:专门用于给JPEG图片写入EXIF数据
执行安装命令:
npm install exifr browser-image-compression piexifjs
2. 修改上传代码
替换原有的resizeFile逻辑,整合EXIF提取、图片压缩、元数据注入:
import exifr from 'exifr' import imageCompression from 'browser-image-compression' import piexif from 'piexifjs' const uploadPicture = async (file: File) => { const jwt = getStorageItem(WebStorageKeys.Jwt) const acceptLanguage = getStorageItem(WebStorageKeys.Lang) || Locales.Ms const imgBody = new FormData() const imageSpec = { maxWidth: 2048, maxHeight: 2048, compressFormat: 'JPEG', quality: 80, rotation: 0 } // 提取原图片的EXIF和GPS数据 const exifData = await exifr.parse(file, { exif: true, gps: true }) // 转成piexif能处理的格式 const exifStr = piexif.dump(exifData) // 压缩图片 const compressedFile = await imageCompression(file, { maxWidthOrHeight: imageSpec.maxWidth, fileType: imageSpec.compressFormat, initialQuality: imageSpec.quality / 100, useWebWorker: true // 开启Web Worker提升压缩性能 }) // 把EXIF注入到压缩后的图片中 const injectExif = async (compressedFile: File, exifStr: string): Promise<File> => { return new Promise((resolve) => { const reader = new FileReader() reader.onload = (e) => { const base64Raw = (e.target?.result as string).replace(/^data:image\/jpeg;base64,/, '') // 注入EXIF const newBase64 = piexif.insert(exifStr, base64Raw) // 转回File对象 const blob = imageCompression.convertBase64ToBlob(`data:image/jpeg;base64,${newBase64}`) resolve(new File([blob], file.name, { type: 'image/jpeg' })) } reader.readAsDataURL(compressedFile) }) } const finalFile = await injectExif(compressedFile, exifStr) imgBody.append('photo', finalFile, finalFile.name) imgBody.append('submissionId', submission?._id || '') const res = await fetch(`${config.gateway.baseUrl}/api/submissions/upload-image`, { method: 'POST', headers: { Authorization: `Bearer ${jwt}`, 'accept-language': acceptLanguage }, body: imgBody }) const data = await res.json() return { url: data.url } }
关键细节
- 只针对JPEG格式有效,PNG的元数据格式不同,如需处理PNG可单独用
exifr解析PNG元数据,配合对应工具写入 - 如果不需要GPS信息,可以在
exifr.parse里去掉gps: true选项,减少数据量 - 老旧浏览器不支持Web Worker的话,把
useWebWorker设为false即可
内容的提问来源于stack exchange,提问作者Riefqi
相关产品推荐
相关产品推荐

