如何用MetadataExtractor通用获取图片/视频的原始创建时间?
问题
我正在开发一个用于迁移相机或手机拍摄的图片、视频的程序,涉及相机/手机拍摄的.jpg文件、iPhone拍摄的.mov视频、.png截图等多种格式。我需要获取文件的原始创建时间(而非文件写入时间)。
目前我已找到针对.jpg文件获取该时间的代码:
IEnumerable<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(filename); var subIfdDirectory = directories.OfType<MetadataExtractor.Formats.Exif.ExifSubIfdDirectory>().FirstOrDefault(); var dateTime = subIfdDirectory?.GetDescription(MetadataExtractor.Formats.Exif.ExifSubIfdDirectory.TagDateTimeOriginal);
以及针对.mov文件的获取代码:
var subIfdDirectory = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory>().FirstOrDefault(); var dateTime3 = subIfdDirectory?.GetDescription(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated);
但这种需要先判断文件格式再调用对应目录获取标签的方式较为繁琐。请问是否存在更通用的实现方式,例如:
IEnumerable<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(filename); var dateTime = directories.GetTag(TagDateTimeOriginal) if (dateTime != null) <use value here> dateTime = directories.GetTag(TagCreated) if (dateTime != null) <use value here>
或者是否有其他更简洁的示例代码?
回答
可以通过遍历所有目录、按优先级查找目标标签的方式实现通用逻辑,无需预先判断文件格式。以下是具体实现:
核心思路
- 定义时间标签优先级列表,按优先级从高到低排列(比如优先取照片的原始拍摄时间,再取视频的创建时间,最后补充兜底选项)
- 遍历所有元数据目录,逐个检查是否包含目标标签,找到第一个有效时间就返回
示例代码
using MetadataExtractor; using MetadataExtractor.Formats.Exif; using MetadataExtractor.Formats.QuickTime; using System.IO; using System.Linq; public static DateTime? GetOriginalCreationTime(string filename) { var directories = ImageMetadataReader.ReadMetadata(filename); // 按优先级定义需要查找的标签,可根据需求扩展 var tagPriorityList = new[] { (DirType: typeof(ExifSubIfdDirectory), TagId: ExifSubIfdDirectory.TagDateTimeOriginal), (DirType: typeof(QuickTimeTrackHeaderDirectory), TagId: QuickTimeTrackHeaderDirectory.TagCreated), (DirType: typeof(ExifIfd0Directory), TagId: ExifIfd0Directory.TagDateTime), // 可补充PNG、其他视频格式的时间标签 }; foreach (var (DirType, TagId) in tagPriorityList) { var targetDir = directories.FirstOrDefault(dir => dir.GetType() == DirType); if (targetDir != null && targetDir.TryGetDateTime(TagId, out var creationTime)) { return creationTime; } } // 所有元数据标签都找不到时,可降级返回文件系统的创建时间(可选) return new FileInfo(filename).CreationTimeUtc; }
说明
- 使用
TryGetDateTime直接获取DateTime类型结果,避免手动解析字符串的麻烦 - 按优先级查找能确保优先拿到最准确的原始时间(比如照片的
DateTimeOriginal比文件系统时间更可靠) - 可以根据支持的文件格式,扩展
tagPriorityList加入对应标签(比如PNG的创建时间标签、其他视频格式的时间标签)
内容的提问来源于stack exchange,提问作者dcole
相关产品推荐
相关产品推荐

