You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:27:40