Check selected file matches accept attribute on an <input> tag

后端 未结 3 1415
隐瞒了意图╮
隐瞒了意图╮ 2021-01-16 00:37

I wish to prevent the user from uploading a file the server will reject from a page with minimal JavaScript on it, ideally without adding any heavy dependencies like jQuery

3条回答
  •  太阳男子
    2021-01-16 01:23

    You could just perform a RegExp test — the following converts the wildcard in MIME type strings to match RegExp syntax, and tests that against the input file's type:

    ( new RegExp( i.accept.replace( '*', '.\*' ) ) ).test( i.files[ 0 ].type )
    

    Demo here.

    EDIT:

    I eventually found a way to make this functionality seamless with native browser validation behaviour (ie prevent submission for invalid inputs, notify user using native validation warnings), but I'm not exactly sure how the code works or whether it's good practice (I've asked about the stranger parts here). However, this appears to behave as expected, at least in 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 );
        } );
    }();
    

    Demo here (attempt to submit with an invalid file type).

提交回复
热议问题