如何在不使用库的情况下读取文件Node.js中超出fs.statSync提供的元数据?

cu6pst1q  于 2022-11-04  发布在  Node.js
关注(0)|答案(1)|浏览(90)

这是一个我似乎无法在Node.js文档上找到答案的主题(我知道这是可能的,因为有像exif这样的库),我也无法在互联网上找到答案,除非每个人都说只使用库。
我不想使用库,所以我想在本地完成这项工作,并学习更多关于读取文件元数据的知识,也许最终在构建自己的迷你工具时也会更新元数据。
如果我运行类似fs.statSync()的代码,我可以获得Stats对象中返回的通用元数据;但是,在我的情况下,我寻找 * 所有其他 * 元数据,而不仅仅是基本的文件信息,如sizebirthtime等。

我需要其他元数据,如 * dimensionsdate taken,尤其是您在图像、视频或音频文件中看到的内容*。

也许有这样的东西:

const deepMetaData = fs.readFileSync().getMetaDataAsString();
console.info(/Date Taken/.test(deepMetaData)); // true

const deepMetaData = fs.createReadStream().buffer().toString();
const dateTaken = deepMetaData.match(/Date Taken: (\d{4}-\d{2}-\d{2})/)[1];
console.info(dateTaken);

如果我需要处理缓冲区、流等,而不是字符串输出,这也很酷。最好是同步的。所以如果有人能提供一个简单的例子,说明如何在没有库的情况下读取这种元数据,我至少可以从中查找使用的方法,以便以后了解更多,并利用与任何方法相关的文档。谢谢!

zkure5ic

zkure5ic1#

Nodejs fs函数如fs.statSync()只提供文件的操作系统级元数据(如createDate,modificationDate,file size等)。这些是文件在文件系统中的属性。它们与文件本身的实际数据没有任何关系。
当您谈到EXIF时(对于照片),这是从文件数据本身解析的。要了解这种类型的数据,您必须至少读取和解析文件的开头,并且必须能够识别和理解您可能遇到的所有不同文件格式。对于照片,这将包括JPEG、PNG、HEIC、GIF、每一种都有不同的文件格式,并且需要唯一的代码来理解嵌入在文件中的元数据。

Nodejs不支持任何内置的。

因此,它需要为每种文件类型定制代码。如果你还想包含其他类型的文件,如视频,你需要扩展你的列表,你可以读取,解析和理解不同的文件类型。对于你所谈论的文件的深度,这是一个大工作,特别是当涉及到测试所有不同的文件和元数据的变体存在于野外。
我个人可以为JPEG这样的特定文件类型实现自己的代码,但如果我的任务是支持几十种类型的文件,特别是支持广泛的视频文件格式,我会立即从现有的库中寻求帮助,这些库已经完成了所有耗时的工作,研究、编写和测试如何正确读取和理解所有变体。
我知道这是可能的,因为像exif这样的库
这是一个库的示例,它读取图像文件的开头,根据预期的格式对其进行解析,并知道如何解释EXIF头中所有可能的标记及其含义。
因此,如果有人能提供一个简单的例子,说明如何在没有库的情况下读取这种元数据
学习EXIF库的代码并了解它是如何工作的。如果您打算自己实现它,我仍然不明白为什么要避免使用已经存在的工作库,这是nodejs生态系统的最大优势之一-您可以在现有的所有开放源代码的基础上进行构建,而不必自己从头开始重新实现,并将编码时间花在其他人尚未实现。
如何使用节点读取元数据?
你必须从文件中读取数据(通常在文件的开头)。您可以使用fs模块提供的任何机制。例如,您可以使用fs.createReadStream(),然后在文件中进行流传输,在数据到达时解析和解释它,然后在超过元数据结尾时停止流传输。您可以使用fs.open()打开文件句柄并使用fs.read()读取文件的块,直到您已经读取了足够多的内容以获得所有元数据。
你有一个例子就在你面前,它的代码在NPM的EXIF库中做这件事,你似乎已经知道了。只要去检查它的代码。代码都在那里。
我只是在寻找一个简单的答案来获得信息,即使它是一个字符串。
这也许是你的主要问题。没有简单的答案来获得这些信息,它也不只是作为一个字符串的blob存在。这些文件有时是二进制文件(出于空间效率的原因)。你必须学习如何读取和解析二进制数据。去研究EXIF库中的the code,看看它已经在做什么,你可以从中学习。没有更好的例子可以开始了。
但是,对于一个使用heic文件类型的简单示例,这将获取文件元数据的前5000个字符,然后可以搜索这些字符:

const fileDescriptor = fs.openSync(absPathToHeicPhoto);
const charCount = 5000;
const buffer = Buffer.alloc(charCount);
const headerBytes = fs.readSync(fileDescriptor, buffer, 0, charCount);
const bufferAsStr = buffer.toString('utf8', 0, charCount);
console.info(/\d{4}:\d{2}:\d{2}/.test(bufferAsStr));

仅供参考,我在NPM上查看了这个EXIF库的代码,它的实现很差。它使用fs.readFile()将整个映像加载到RAM中(即使它只需要文件开始处的一小部分数据)。由于这个原因,这是一个很差的实现(内存和磁盘效率低下)。
但是,它确实有一个名为processImage的方法和一个名为extractExifData的方法,用于处理文件的二进制数据,解析出EXIF信息。这些是指向其实际代码的链接。您可以从那里开始学习。
仅供参考,作为一名摄影师,我使用了一个名为exiftool的命令行程序,该程序将exif信息转储到stdout或一个文件中,用于存储许多图像。作为一种不同的方法,您可以从nodejs程序(使用child_process模块)运行该工具,并捕获其输出并使用该输出,让它完成您在生成的输出上操作的繁重工作。

相关问题