Я хочу, чтобы пользователь не загружал файл, который сервер будет отклонять со страницы с минимальным JavaScript на нем, в идеале без добавления каких-либо тяжелых зависимостей, таких как jQuery, исключительно для решения этой проблемы.
Поскольку я не настроен на использование устаревших пользователей, я использовал систему проверки формы браузера, чтобы проверить, выбрал ли пользователь допустимый файл, однако кажется, что только пользователь выбирает файл независимо от типа.
> i = document.querySelector('input[type=file]')
<input type="file" accept="image/*" name="attachment" required>
> i.accept
"image/*"
> i.files[0].type
"application/x-zip-compressed"
> i.checkValidity()
true
Есть ли простой способ сделать это? Единственное, что я обнаружил, что близко, это jQuery Validate, но это немного сложное решение.
Вы можете просто выполнить тест RegExp - следующий преобразует подстановочный знак в строках типа MIME для соответствия синтаксису RegExp и проверяет его на тип входного файла:
( new RegExp( i.accept.replace( '*', '.\*' ) ) ).test( i.files[ 0 ].type )
РЕДАКТИРОВАТЬ: В конце концов, я нашел способ сделать эту функциональность без изменений с учетом поведения браузера (т.е. Предотвратить отправку недопустимых входов, уведомить пользователя, используя встроенные предупреждения проверки), но я не совсем точно знаю, как работает код, или это хорошая практика (I ' вы спрашивали о чужой части здесь). Однако, похоже, это ведет себя так, как ожидалось, по крайней мере в Chrome 31:
void function enhanceFileInputTypeValidityCheck(){
var inputPrototype = document.createElement( 'input' ).constructor.prototype;
var nativeCheckValidity = inputPrototype.checkValidity;
function validateFileInputType( input ){
var MIMEtype = new RegExp( input.accept.replace( '*', '.\*' ) );
return Array.prototype.every.call( input.files, function passesAcceptedFormat( file ){
return MIMEtype.test( file.type );
} );
}
function validateInputs(){
Array.prototype.forEach.call( document.querySelectorAll( 'input, select' ), function callValidation( input ){
input.checkValidity();
} );
}
inputPrototype.checkValidity = function enhancedCheckValidity(){
if( this.type === 'file' && this.accept && this.files && this.files.length ){
if( !validateFileInputType( this ) ){
this.setCustomValidity( 'Please only submit files of type ' + this.accept );
return false;
}
}
return nativeCheckValidity.apply( this );
}
Array.prototype.forEach.call( [ 'change', 'input' ], function bindValidation( event ){
document.documentElement.addEventListener( event, validateInputs );
} );
}();
Демо здесь (попытка отправить с недопустимым типом файла).