【问题标题】:JavaScript: can I read EXIF data from a file upload input?JavaScript:我可以从文件上传输入中读取 EXIF 数据吗?
【发布时间】:2011-08-12 16:05:49
【问题描述】:

我有以下任务:

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

所以,我想在将文件添加到input 时使用 JavaScript 提取一些 EXIF 数据。

这可能吗?

我知道这个问题:Can I read Exif data of a picture in the client-side with js?,指的是http://blog.nihilogic.dk/2008/05/reading-exif-data-with-javascript.html

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

感谢您的建议。

【问题讨论】:

  • 在开始上传之前,我设法让它在客户端工作:检查this question 和我的答案!
  • 嗨西蒙,考虑更新接受的答案。

标签: javascript jquery image exif


【解决方案1】:

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

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

获取 EXIF:

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

我不得不稍微调整一下库来让它做我想做的事情(我想要一个 commonJS 库)我还做了问题 1 中确定的调整。

Here is a fiddle

【讨论】:

  • 哇...在一篇文章中有很多 个链接。
  • 我的意思是指向同一页面的这么多链接往往会使帖子看起来像垃圾邮件,我认为这不是您想要的。只需将 jsjpegmeta 的第一次或最后一次提及作为链接,其余的则保留正常文本。
【解决方案2】:

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

有一个新库 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)
})

您还可以试用库的 playground 并尝试图像及其输出,或查看 repository and docs

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      Shaanimal 的回答是正确的,但它总是让我惊讶于人们制造事物的复杂程度。如果您不需要支持多个文件上传,这里是完成相同事情的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>
      

      【讨论】:

        【解决方案5】:

        我刚刚从 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}
        />    
        

        结果应该是这样的。

        【讨论】:

          【解决方案6】:

          我喜欢乐观。我喜欢它被完全压碎时发出的那种破烂声。

          不,JavaScript 不能直接访问 EXIF;这不是安全问题,它只是浏览器无法提供给 DOM 的东西。

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

          【讨论】:

          • 是的,这不是真的。如果通过 AJAX 获取,JS 可以愉快地读取二进制数据。之后,就是从文件中解析出 EXIF 数据的问题,这正是链接到的页面所做的事情。
          • 它不可用因为这是一个安全问题。
          • @cwolves -- 谢谢,我没有仔细阅读链接页面。不过,我不会将 JS 的经历描述为使其快乐。在所有琐碎的事情、特定于浏览器的东西和同源策略之间,我想象中的拟人化的 JS 会呜咽着求饶。但它会工作......
          • 我不确定我是否百分百同意你的警察工作,@alex。如果 JS 有权 上传 它,我不明白为什么读取前几个字节会构成新的安全漏洞。
          • @Malvolio:JS没有权限上传,浏览器有。 JS只能指挥浏览器做做做做。它不能靠自己做事:)
          【解决方案7】:

          不,抱歉。在将文件数据上传到服务器之前,您无法访问任何文件数据,这肯定是您链接到的库所做的。文件上传后,您可以将其保存在某处,重新下载并从中读取 EXIF 数据。

          上面的答案曾经是正确的,但现在大多数现代浏览器都允许通过 js 文件 api 访问文件。随意使用它,但如果需要跨浏览器支持,您也应该使用服务器端解决方案。

          【讨论】:

          • 不是这样,现代浏览器的文件数据可以通过javascript访问
          • 这是非常不真实的。这是一个公认的答案,其他人认为这是事实,这一事实很疯狂。我不仅在生产中运行它,而且在这里得到证明:jsfiddle.net/xQnMd/1
          • @JohnClarkeMills -- 你说得对,我应该说它是不可能跨浏览器的,在回答这个问题时,即使使用最新版本的 chrome 也是不可能的,火狐。它仅在开发版本中可用。即使澄清了,正确的答案仍然是“上传它并读取数据,如果你想花时间,也可以使用js文件api”
          • 这个答案不正确。你当然可以在客户端访问文件数据,而不需要等到上传到服务器才能访问。
          • @ObiWan -- 这个问题已有 2.5 年历史。 2.5 年前的答案是正确的。
          猜你喜欢
          • 1970-01-01
          • 2016-04-15
          • 2022-06-10
          • 2022-01-15
          • 2015-10-11
          • 1970-01-01
          • 2013-10-25
          • 2012-05-07
          • 1970-01-01
          相关资源
          最近更新 更多