JavaScript:我可以从文件上传输入读取 EXIF 数据吗?

发布于 2024-11-03 04:45:40 字数 718 浏览 4 评论 0 原文

我有以下任务:

  • 提供
  • 当用户添加文件时 :
    • 读取 EXIF 数据(具体来说,位置信息(如果有))
    • 使用 Ajax 将文件和信息从 EXIF 发送到外部 API

因此,我想使用 JavaScript 在文件打开时提取一些 EXIF 数据添加到输入

这可能吗?

我知道这个问题: 能否在客户端用js读取图片的Exif数据?,参考http://blog.nihilogic.dk/2008/05/reading-exif-data-with-javascript.html

但我的问题是(我认为? )略有不同 - 我想在图像位于我的域之前提取 EXIF 数据,而它位于用户的本地文件系统上,如果您明白我的意思的话。我可以访问二进制数据,那么我也可以获得 EXIF 吗?

谢谢你的建议。

I have the following task:

  • Offer an <input type=file />
  • When the user adds a file:
    • read the EXIF data (specifically, location information if available)
    • send the file and the information from the EXIF to an external API, using Ajax

So, I'd like to use JavaScript to extract some EXIF data when a file is added to the input.

Is this possible?

I know about this question: Can I read Exif data of a picture in the client-side with js? , which refers to http://blog.nihilogic.dk/2008/05/reading-exif-data-with-javascript.html

But my question is (I think?) slightly different - I want to extract the EXIF data before the image is even on my domain, while it's on the user's local filesystem, if you see what I mean. I can access the binary data, so can I get the EXIF too?

Thanks for your advice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

葬花如无物 2024-11-10 04:45:41

您可以使用 HTML5 在客户端上执行此操作。对于不支持 File 和 FileReader 的旧浏览器,您应该有一个适当的基于服务器的后备。

您可以编写自己的 exif 解析器或使用 jsjpegmeta 库(Ben Leslie),它是一个简单+很棒的库,可以让浏览器从大多数 jpeg 文件中提取 EXIF 数据。有一个补丁表示它修复了大部分兼容性问题。我还没有测试过这个补丁,但是准备好 fork 这个项目并戴上你的 github 帽子。

要获取 EXIF:

  1. 打开文件对话框: 我通常创建一个按钮,调用一个函数来生成 输入并添加更改handler
  2. 获取文件: 在文件更改处理程序 ue $(this).get(0).files 中获取所选文件的列表。
  3. 解析 exif 数据:将浏览结果发送到 jsjpegmeta

我必须对库进行一些调整才能让它执行我想要的操作(我想要一个 commonJS 库)我还进行了问题 1 中确定的调整

这是一个小提琴

更新 26.07.2022
该软件包已移至 Gitlab。该补丁已包含在最新版本中。您可以在此处找到该软件包。

You can do this on the client with HTML5. You should have an appropriate server based fallback for older browsers that don't support File and FileReader.

You can write your own exif parser or use the jsjpegmeta library(Ben Leslie), which is a simple+awesome library that lets the browser extract the EXIF data from most jpeg files. There is a patch that says it fixes most of the compatibility problems. I haven't tested the patch, but be prepared to fork the project and put on your github hat.

To get the EXIF:

  1. Open file dialog: I usually create a button that calls a function to generate the <file input and add a change handler
  2. Get the files: In the file change handler ue $(this).get(0).files to get the list of selected files.
  3. Parse the exif data: Send the browse results to jsjpegmeta

I had to tweak the library a bit to get it to do what I wanted (I wanted a commonJS library) I also made the tweak identified in issue 1.

Here is a fiddle

Update 26.07.2022
The package has been moved to Gitlab. The patch is included in the newest version. You can find the package here.

梦幻之岛 2024-11-10 04:45:41

我知道这可能已经解决了,但我想为遇到这个问题的人们提供一个替代解决方案。

有一个新的库 exifr 您可以使用它来做到这一点。它是一个维护、积极开发的库,重点关注性能,并且可以在 Nodejs 和浏览器中运行。

从一个文件中提取 exif 的简单示例:

document.querySelector('#filepicker').addEventListener('change', async e => {
  let file = e.target.files[0]
  let exifData = await exif.parse(file)
  console.log('exifData', exifData)
})

从多个文件中提取 exif 的复杂示例:

document.querySelector('#filepicker').addEventListener('change', async e => {
    let files = Array.from(e.target.files)
    let promises = files.map(exif.parse)
    let exifs = await Promise.all(promises)
    let dates = exifs.map(exif => exif.DateTimeOriginal.toGMTString())
    console.log(`${files.length} photos taken on:`, dates)
})

您甚至可以提取嵌入在文件中的缩略图:

let img = document.querySelector("#thumb")
document.querySelector('input[type="file"]').addEventListener('change', async e => {
  let file = e.target.files[0]
  img.src = await exifr.thumbnailUrl(file)
})

您还可以尝试该库的 游乐场 并尝试图像及其输出,或者查看 存储库和文档

I know this may be already solved but I'd like to offer an alternative solution, for the people stumbling upon this question.

There's a new library exifr with which you can do exactly that. It's maintained, actively developed library with focus on performance and works in both nodejs and browser.

Simple example of extracting exif from one file:

document.querySelector('#filepicker').addEventListener('change', async e => {
  let file = e.target.files[0]
  let exifData = await exif.parse(file)
  console.log('exifData', exifData)
})

Complex example of extracting exif from multile files:

document.querySelector('#filepicker').addEventListener('change', async e => {
    let files = Array.from(e.target.files)
    let promises = files.map(exif.parse)
    let exifs = await Promise.all(promises)
    let dates = exifs.map(exif => exif.DateTimeOriginal.toGMTString())
    console.log(`${files.length} photos taken on:`, dates)
})

And you can even extract thumbnail thats embedded in the file:

let img = document.querySelector("#thumb")
document.querySelector('input[type="file"]').addEventListener('change', async e => {
  let file = e.target.files[0]
  img.src = await exifr.thumbnailUrl(file)
})

You can also try out the library's playground and experiment with images and their output, or check out the repository and docs.

多像笑话 2024-11-10 04:45:41

2023 年来到这里,因为寻找类似的解决方案。所有答案中提到的库似乎都已经过时了。但是,npm 上有一个维护的库: https://www.npmjs.com/package/exifreader

为了在客户端读取 exif,我们可以这样使用它:

在 html 中包含 lib

读取图像文件并提取exif

// example code adapted from exifreader docs
document.querySelector('input[type="file"]').addEventListener('change', async e => {
    const file = e.target.files[0];
    const tags = await ExifReader.load(file);
    // example exif tag access
    const imageDate = tags['DateTimeOriginal'].description;
    const unprocessedTagValue = tags['DateTimeOriginal'].value;
    // ...more processing here
})

Came here in 2023 because looking for a similar solution. The libraries mentioned in all answers seem pretty outdated. However there is a maintained lib on npm: https://www.npmjs.com/package/exifreader

For reading exif on client-side we can use it like this:

include lib in html

<script src="/path/to/exif-reader.js"></script>

read image file and extract exif

// example code adapted from exifreader docs
document.querySelector('input[type="file"]').addEventListener('change', async e => {
    const file = e.target.files[0];
    const tags = await ExifReader.load(file);
    // example exif tag access
    const imageDate = tags['DateTimeOriginal'].description;
    const unprocessedTagValue = tags['DateTimeOriginal'].value;
    // ...more processing here
})
梦魇绽荼蘼 2024-11-10 04:45:41

我刚刚从 npm 找到了“exif-js”。

https://github.com/exif-js/exif-js

我是在反应中这样做。
这是我的代码。
它对我来说非常有效,

import EXIF from 'exif-js';

//......

const fileChangedHandler = (event) => {
    const files = event.target.files;
    console.log(files[0]);
    EXIF.getData(files[0], function () {
        console.log(EXIF.getAllTags(this));
    });
};


//......

<input
    type="file"
    onChange={fileChangedHandler}
/>    

结果应该是这样的。

输入图片此处描述

I've just found 'exif-js' from npm.

https://github.com/exif-js/exif-js

I'm doing this in react.
this is my code.
it worked for me very well

import EXIF from 'exif-js';

//......

const fileChangedHandler = (event) => {
    const files = event.target.files;
    console.log(files[0]);
    EXIF.getData(files[0], function () {
        console.log(EXIF.getAllTags(this));
    });
};


//......

<input
    type="file"
    onChange={fileChangedHandler}
/>    

The result should be like this.

enter image description here

离旧人 2024-11-10 04:45:41

是的,使用现代浏览器,您可以读取文件内容并提取 exif。您显示的链接是一个示例。问题是,在旧浏览器 IE6-9、FF 3.6 上,这是不可能的。您还应该考虑浏览器从大文件中读取和提取 exif 是一个困难的过程。

Yes with modern browser you can read files contents and so extract exif. the link you show is an example. the problem is that on old browsers IE6-9, FF 3.6- this is not possible. Also you should consider the it is a hard process for browser to read and extract exif from big files.

白色秋天 2024-11-10 04:45:41

Shanimal 的答案是正确的,但它使事情变得过于复杂。这是 jsjpegmeta 库的实现,它可以完成相同的事情,如果您不需要支持多个文件上传:

<input type="file" accept="image/jpeg" id="input" />
<script src="./jsjpegmeta.js"></script>
<script>
document.getElementById('input').onchange = function(e) {
  var file = e.target.files[0],
    fr = new FileReader();
  fr.onloadend = function() {
    console.log(new JpegMeta.JpegFile(this.result, file.name));
  };
  fr.readAsBinaryString(file);
};
</script>

Shanimal's answer is correct, but it overcomplicates things. Here is an implementation of the jsjpegmeta library that accomplishes the same thing, if you don't need to support multiple file uploads:

<input type="file" accept="image/jpeg" id="input" />
<script src="./jsjpegmeta.js"></script>
<script>
document.getElementById('input').onchange = function(e) {
  var file = e.target.files[0],
    fr = new FileReader();
  fr.onloadend = function() {
    console.log(new JpegMeta.JpegFile(this.result, file.name));
  };
  fr.readAsBinaryString(file);
};
</script>
凉薄对峙 2024-11-10 04:45:41

不,JavaScript 无法直接获取 EXIF;这不是一个安全问题,它只是浏览器无法向 DOM 提供的内容。

您得到的最接近的正是另一个问题提到的 hack:在服务器端有一个进程来分析图像并通过 AJAX 返回 EXIF 数据>。

No, JavaScript cannot get to EXIF directly; this is not a security issue, it's just something that isn't made available by the browser to the DOM.

The closest you get get is exactly the hack that the other question referred to: have a process on the server side to analyze the image and return the EXIF data via AJAX>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文