JavaScript: can I read EXIF data from a file upload input?
Asked Answered
P

7

11

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.

Patsis answered 25/4, 2011 at 23:43 Comment(1)
I managed to get it working on client side before the upload has been started: check this question and my answer!Pulling
T
7

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.

Tamathatamaulipas answered 16/10, 2012 at 16:50 Comment(0)
G
4

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.

Gloom answered 12/11, 2019 at 9:57 Comment(0)
L
1

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

Leaflet answered 30/8, 2021 at 7:42 Comment(0)
S
0

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.

Speak answered 5/6, 2012 at 7:55 Comment(0)
G
0

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>
Gestate answered 22/11, 2016 at 21:8 Comment(0)
S
0

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
})
Spoonful answered 12/8, 2023 at 8:35 Comment(0)
M
-5

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>.

Mcmillan answered 25/4, 2011 at 23:50 Comment(6)
yeah, that's not true. JS can happily read binary data if you fetch it via AJAX. After that, it's a matter of parsing EXIF data out of the file, which is exactly what the page linked to does.Izmir
It isn't made available because it'd be a security issue.Pulling
@cwolves -- thanks, I didn't read the linked page closely. I wouldn't describe what JS goes through as making it happy, though. Between all the bit-twiddling, the browser-specific stuff, and the same-source policy, the anthropomorphized JS of my imagination would be whimpering and pleading for mercy. But it would work...Mcmillan
I'm not sure I agree with you a hundred percent on your police work, there, @Pulling . If the JS has the authorization to upload it, I don't see why reading the first few bytes would constitute a fresh hole in the security.Mcmillan
@Malvolio: JS doesn't have the authority to upload it, the browser does. JS can only direct the browser to do so and so. It can't do diddly on its own :)Aronson
@CyrilGupta -- JS does what ?Mcmillan

© 2022 - 2024 — McMap. All rights reserved.