Тип Mime отсутствует для .rar и .tar

Javascript (Windows 8.1, Firefox), похоже, не имеет типов mime для файлов .tar или .rar файлов (и, возможно, других, это единственные два, которые я нашел). Что с этим? Есть ли что-нибудь, что я могу использовать для решения этой проблемы? Мне бы очень хотелось, чтобы вы могли получать типы mime для этих типов файлов, не делая какого-то странного взлома расширения.

Я сделал скрипку, чтобы доказать эту проблему: http://jsfiddle.net/kungfujoe/jd8h7wvs/

Если вы перейдете на .txt или .docx или так много других форматов, тип будет удален. Однако оба .tar и .rar не тянут их. Нечетный, верно?

(код JSFiddle ниже)

HTML

<input id='button' type='file' name='file'/>
<div id='out'>Output Goes Here</div>

Javascript (с использованием JQuery 2.1.0)

$('#button').unbind('change');
$('#button').bind('change', function () {
    if(this.files[0] !== undefined && this.files[0] !== null) {
        document.getElementById("out").innerHTML = "Type is " + this.files[0].type.toString();        
    } else {
        throw "Error"
    }
});

Спасибо

ИЗМЕНИТЬ

1) Обновленный вопрос, чтобы отразить, что проблема была обнаружена в Windows 8.1 Firefox. Chrome имеет тип mime для файлов tar, но не rar файлов.

2) Добавлен jQuery для скрипта

Ответ 1

JQuery просто обертывает базовый API файлов, используемый в большинстве браузеров, поэтому нет никакой разницы в том, как JQuery и Javascript обрабатывают файлы и типы mime. Вот спецификация API файлов:

http://www.w3.org/TR/FileAPI/#dfn-type

Объект File, который вы управляете, наследует свойство типа из объекта Blob, а браузер использует blob (массив байтов) для определения типа mime.

Для выполнения этой задачи каждый браузер реализует алгоритм sniffing файла для "чтения" типа mime из массива байтов, и если тип mime не соответствует, он возвращает пустую строку, как в вашем сценарии выше.

Вот полный алгоритм spec:

https://mimesniff.spec.whatwg.org/

Итак, теперь вам интересно, почему он не работает для файлов TAR, ZIP и RAR и почему он работает для некоторых людей, а не для вас?.. потому что алгоритм поиска файлов явно не идеален.

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

Например, я использовал WinRaR в окне Windows 8 для сжатия файла, а начальные байты созданного файла:

52 61 72 21 1A 07 00

Однако, чтобы распознать его как .RAR, алгоритм сопоставления шаблонов байтов браузера ожидает

52 61 72 20 1A 07 00

Как вы видите, есть небольшая разница, и когда я загрузил свой RAR файл в браузер, используя ваш код выше, Firefox не смог распознать Mime-Type, и я получил пустую строку в свойстве type.

Однако, когда я упаковал ZIP файл с помощью WinRar на том же компьютере с настройками по умолчанию, он генерирует начальную последовательность байтовых массивов 50 4B 03 04, которая соответствует шаблону zip-байта, ожидаемому алгоритмом, и когда я использовал ваш код выше он смог правильно определить тип мим как application/zip!

Итак, как вы видите из моего объяснения, это вопрос сериализации и "несовершенства" алгоритма, который соответствует сериализованным байтам с расширениями mime в браузерах.

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

Если вы хотите придерживаться клиента, вы можете использовать следующую библиотеку JS:

https://github.com/rsdoiel/mimetype-js

И тогда обнаружение типа mime будет состоять из одной строки кода:

mimetype.lookup("myfile.rar")

Вот рабочий скрипт, обновляющий ваш пример, чтобы использовать mimetype js:

http://jsfiddle.net/jd8h7wvs/4/