JavaScript: могу ли я прочитать данные EXIF ​​из ввода для загрузки файла?

У меня следующая задача:

  • Предложите <input type=file />
  • When the user adds a file:
    • read the EXIF data (specifically, location information if available)
    • отправить файл и информацию из EXIF ​​во внешний API, используя Ajax

Итак, я хотел бы использовать JavaScript для извлечения некоторых данных EXIF, когда файл добавляется в input.

Это возможно?

Я знаю об этом вопросе: Могу ли я прочитать данные Exif изображения на стороне клиента с помощью js?, который относится к http://blog.nihilogic.dk/2008/05/reading-exif-data-with-javascript.html

Но мой вопрос (я думаю?) Немного другой - я хочу извлечь данные EXIF ​​до того, как изображение окажется даже в моем домене, пока оно находится в локальной файловой системе пользователя, если вы понимаете, что я имею в виду. Я могу получить доступ к двоичным данным, могу ли я получить и EXIF?

Спасибо за ваш совет.


person simon    schedule 25.04.2011    source источник
comment
Мне удалось заставить его работать на стороне клиента до начала загрузки: проверьте этот вопрос и мой ответ!   -  person alex    schedule 27.04.2012
comment
Привет, Саймон, подумайте об обновлении принятого ответа.   -  person Alex    schedule 10.08.2016


Ответы (6)


Нет, извините. Вы не можете получить доступ к каким-либо данным файла, пока они не будут загружены на сервер, что, безусловно, делает библиотека, с которой вы связались. После загрузки файла вы можете где-нибудь сохранить его, повторно загрузить и прочитать из него данные EXIF.

Приведенный выше ответ был правильным, но большинство современных браузеров теперь разрешают доступ к файлам через apis js-файла. Не стесняйтесь использовать это, но вы также должны использовать серверное решение, если требуется кроссбраузерная поддержка.

person Mark Kahn    schedule 25.04.2011
comment
это неправда, в современном браузере к данным файла можно получить доступ из javascript - person albanx; 05.06.2012
comment
это ОЧЕНЬ неправда. Тот факт, что это общепринятый ответ, и другие считают, что это правда, безумие. Мало того, что это работает в производственной среде, это доказано прямо здесь: jsfiddle.net/xQnMd/1. - person John Clarke Mills; 16.12.2012
comment
@JohnClarkeMills - Вы правы, я должен был сказать, что кроссбраузерность невозможна, и в то время, когда на это был дан ответ, это было невозможно даже с последними сборками chrome, firefox. Это было доступно только в сборках для разработчиков. Даже с уточнением правильным ответом все равно было загрузить его и прочитать данные, и если вы хотите потратить время, также используйте apis js файла. - person Mark Kahn; 17.12.2012
comment
Это неверный ответ. Вы, безусловно, можете получить доступ к данным файла на стороне клиента, и вам не нужно ждать, пока он будет загружен на сервер, чтобы получить к нему доступ. - person Obi Wan; 21.10.2013
comment
@ObiWan - этому вопросу 2,5 года. Ответ был правильным 2,5 года назад. - person Mark Kahn; 23.10.2013

Вы можете сделать это на клиенте с HTML5. У вас должен быть соответствующий резервный сервер на основе сервера для старых браузеров, которые не поддерживают File и FileReader.

Вы можете написать свой собственный синтаксический анализатор exif или использовать библиотеку jsjpegmeta (Бен Лесли), которая является простая + потрясающая библиотека, которая позволяет браузеру извлекать данные EXIF ​​из большинства файлов jpeg. Существует патч, в котором говорится, что он устраняет большинство проблем совместимости. . Я не тестировал патч, но будьте готовы разветвить проект и надеть шляпу на github.

Чтобы получить EXIF:

  1. Диалоговое окно открытия файла: я обычно создаю кнопку, которая вызывает функцию для генерации входных данных <file и добавления обработчика изменений.
  2. Получить файлы: в обработчике изменения файлов ue $(this).get(0).files, чтобы получить список выбранных файлов.
  3. Анализируйте данные exif: отправляйте результаты просмотра в jsjpegmeta.

Мне пришлось немного подправить библиотеку, чтобы заставить ее делать то, что я хотел (мне нужна была библиотека commonJS). Я также сделал настройку, указанную в проблеме 1.

Вот скрипка

person Shanimal    schedule 16.10.2012
comment
Вау ... это много ссылок в одном сообщении. - person Andrew Barber; 16.10.2012
comment
Я просто имею в виду, что из-за большого количества ссылок на одну и ту же страницу сообщение выглядит как спам, а я не думаю, что это именно то, что вы намеревались сделать. Просто сделайте первое или последнее упоминание jsjpegmeta ссылкой, а остальной оставьте обычный текст. - person Andrew Barber; 16.10.2012

Я знаю, что это, возможно, уже решено, но я хотел бы предложить альтернативное решение для людей, которые сталкиваются с этим вопросом.

Есть новая библиотека 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 из multile файлов:

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)
})

Вы также можете опробовать игровую площадку библиотеки и поэкспериментировать с изображениями и их выводом или ознакомиться с репозиторий и документы.

person Mike Kovařík    schedule 12.11.2019

Да, в современном браузере вы можете читать содержимое файлов и извлекать exif. ссылка, которую вы показываете, является примером. проблема в том, что в старых браузерах IE6-9, FF 3.6- это невозможно. Также вы должны учитывать, что браузеру сложно читать и извлекать exif из больших файлов.

person albanx    schedule 05.06.2012

Ответ Шанимала верен, но меня не перестает удивлять, насколько излишне сложные люди создают вещи. Вот реализация библиотеки 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>
person mgrahamjo    schedule 22.11.2016

Люблю оптимизм. Мне нравится тот шум, который он издает, когда он полностью раздавлен.

Нет, JavaScript не может напрямую попасть в EXIF; это не проблема безопасности, это просто то, что браузер не делает доступным для DOM.

Самое близкое, что вы получите, - это именно взлом, о котором говорилось в другом вопросе: иметь процесс на стороне сервера для анализа изображения и возврата данных EXIF ​​через AJAX>.

person Malvolio    schedule 25.04.2011
comment
да, это неправда. JS может легко читать двоичные данные, если вы получаете их через AJAX. После этого нужно разобрать данные EXIF ​​из файла, что и делает страница, на которую указывает ссылка. - person Mark Kahn; 26.04.2011
comment
Он недоступен потому что это может быть проблемой безопасности. - person alex; 26.04.2011
comment
@cwolves - спасибо, я не читал внимательно связанную страницу. Однако я бы не назвал то, через что проходит JS, счастливым. Из-за всей этой битвы, специфичных для браузера вещей и политики одного и того же источника антропоморфизированный JS моего воображения будет хныкать и умолять о пощаде. Но это сработает ... - person Malvolio; 26.04.2011
comment
Я не уверен, что согласен с тобой на сто процентов в отношении твоей полицейской работы, @alex. Если у JS есть разрешение на его загрузку, я не понимаю, почему чтение первых нескольких байтов представляет собой новую дыру в безопасности. - person Malvolio; 26.04.2011
comment
@Malvolio: JS не имеет права загружать его, в отличие от браузера. JS может только указать браузеру сделать то-то и то-то. Сам по себе он не может делать ничего :) - person Cyril Gupta; 26.04.2011
comment
@CyrilGupta - JS делает что? - person Malvolio; 26.04.2011