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

React中使用Piexifjs读取JPG的XP Exif标签失败问题

问题描述

在React项目中使用Piexifjs读取JPG文件的EXIF数据,通过Zoner设置了Title=TitleTest、Description=DescriptionTest、Keywords=Keyword1,Keyword2,Keyword3等元数据,但Piexifjs无法读取到XPKeywords等XP标签,仅能在0th/270(ImageDescription)和Exif/37510(UserComment)中找到部分数据,而ExifTool和Windows图片属性均可正常查看这些XP标签数据。

原因分析

Piexifjs对Windows专属的XP系列元数据标签(如XPTitle、XPComment、XPKeywords)的处理存在局限:这些标签的内容采用UTF-16LE编码存储,Piexifjs仅返回原始字节数组,未自动解码为可读字符串;此外需确认piexif.ImageIFD.XPKeywords是否正确映射了XPKeywords的标签ID(0x9C9E)。

解决方案

手动实现UTF-16LE字节数组到字符串的解码,并处理XPKeywords的格式(逗号分隔的关键词)。

修改后的代码如下:

import piexif from "./piexif";

// 解码UTF-16LE字节数组为字符串
function decodeUTF16LE(byteArray) {
  // 去掉末尾可能的空字符(UTF-16LE的空字符是两个0x00)
  while (byteArray.length >= 2 && byteArray[byteArray.length - 1] === 0 && byteArray[byteArray.length - 2] === 0) {
    byteArray = byteArray.slice(0, -2);
  }
  return new TextDecoder('utf-16le').decode(new Uint8Array(byteArray));
}

export function App(props) {
  const fileChangedHandler = (event) => {
    const file = event.target.files[0];

    if (file) {
      var reader = new FileReader();
      reader.onload = function (e) {
        try {
          var exifObj = piexif.load(e.target.result);
          console.log("Exif Data:", exifObj);

          // 确认XPKeywords的标签ID是否正确(0x9C9E对应十进制27790)
          console.log("XPKeywords Tag ID:", piexif.ImageIFD.XPKeywords);

          // 读取并解码XPKeywords
          if (exifObj["0th"] && exifObj["0th"][piexif.ImageIFD.XPKeywords]) {
            const xpKeywordsBytes = exifObj["0th"][piexif.ImageIFD.XPKeywords];
            const xpKeywordsStr = decodeUTF16LE(xpKeywordsBytes);
            // 分割为关键词数组
            const xpKeywords = xpKeywordsStr.split(',').map(k => k.trim()).filter(k => k);
            console.log("XPKeywords:", xpKeywords);
          } else {
            console.log("XPKeywords not found in Exif data.");
          }

          // 同理处理XPTitle标签
          if (exifObj["0th"] && exifObj["0th"][piexif.ImageIFD.XPTitle]) {
            const xpTitleStr = decodeUTF16LE(exifObj["0th"][piexif.ImageIFD.XPTitle]);
            console.log("XPTitle:", xpTitleStr);
          }
        } catch (error) {
          console.error("Error reading Exif data:", error);
        }
      };
      // 改用readAsArrayBuffer避免base64转换的额外开销
      reader.readAsArrayBuffer(file);
    }
  };
  return (
    <div className="App">
      <input type="file" onChange={fileChangedHandler} accept="image/jpeg" />
    </div>
  );
}
关键说明
  • UTF-16LE解码:XP系列标签强制使用UTF-16LE编码,需要用TextDecoder将字节数组转换为字符串,并移除末尾的空终止符。
  • 标签ID确认:如果piexif.ImageIFD.XPKeywords未正确映射0x9C9E,可以直接使用十进制27790替代。
  • 读取方式优化:将readAsDataURL改为readAsArrayBuffer,避免base64编码的额外处理,提升性能。

内容的提问来源于stack exchange,提问作者sliziky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:37:54