检查所选文件是否与 <input> 标记上的接受属性匹配

Lex*_*x R 3 html javascript validation

我希望防止用户上传服务器会从包含最少 JavaScript 的页面拒绝的文件,理想情况下不要添加任何严重的依赖项(例如纯粹为了解决这一问题的 jQuery)。

\n\n

由于我不是针对旧用户,因此我使用浏览器的表单验证系统来检查用户是否选择了有效文件,但它似乎只关心用户是否选择了文件,而不管类型如何。

\n\n
> i = document.querySelector(\'input[type=file]\')\n<input type=\xe2\x80\x8b"file" accept=\xe2\x80\x8b"image/\xe2\x80\x8b*" name=\xe2\x80\x8b"attachment" required>\xe2\x80\x8b\n> i.accept\n"image/*"\n> i.files[0].type\n"application/x-zip-compressed"\n> i.checkValidity()\ntrue\n
Run Code Online (Sandbox Code Playgroud)\n\n

有没有一种简单的方法可以做到这一点?我发现唯一接近的是jQuery Validate,但它是一个重量级的解决方案。

\n

Bar*_*ney 6

您只需执行 RegExp 测试 \xe2\x80\x94 即可将 MIME 类型字符串中的通配符转换为匹配 RegExp 语法,并针对输入文件的类型进行测试:

\n
( new RegExp( i.accept.replace( \'*\', \'.\\*\' ) ) ).test( i.files[ 0 ].type )\n
Run Code Online (Sandbox Code Playgroud)\n

演示在这里

\n编辑:\n

我最终找到了一种方法使此功能与本机浏览器验证行为无缝连接(即防止提交无效输入,使用本机验证警告通知用户),但我不太确定代码是如何工作的或者它是否很好练习(我在这里问过陌生的部分)。然而,这似乎表现符合预期,至少在 Chrome 31 中是这样:

\n
void function enhanceFileInputTypeValidityCheck(){\n    var inputPrototype      = document.createElement( \'input\' ).constructor.prototype;\n    var nativeCheckValidity = inputPrototype.checkValidity;\n\n    function validateFileInputType( input ){\n        var MIMEtype = new RegExp( input.accept.replace( \'*\', \'.\\*\' ) );\n\n        return Array.prototype.every.call( input.files, function passesAcceptedFormat( file ){\n            return MIMEtype.test( file.type );\n        } );\n    }\n    \n    function validateInputs(){\n        Array.prototype.forEach.call( document.querySelectorAll( \'input, select\' ), function callValidation( input ){\n            input.checkValidity();\n        } );\n    }\n\n    inputPrototype.checkValidity = function enhancedCheckValidity(){        \n        if( this.type === \'file\' &&  this.accept && this.files && this.files.length ){\n            if( !validateFileInputType( this ) ){\n                this.setCustomValidity( \'Please only submit files of type \' + this.accept );\n                \n                return false;\n            }\n        }\n\n        return nativeCheckValidity.apply( this );\n    }\n    \n    Array.prototype.forEach.call( [ \'change\', \'input\' ], function bindValidation( event ){\n        document.documentElement.addEventListener( event, validateInputs );\n    } );\n}();\n
Run Code Online (Sandbox Code Playgroud)\n

此处演示(尝试使用无效的文件类型提交)。

\n