Validation of file extension before uploading file
Asked Answered
G

22

114

I am uploading images to a servlet. The validation whether the uploaded file is an image is done in server side only, by checking the magic numbers in the file header. Is there any way to validate the extensions in client side before submitting the form to servlet? As soon as I hit enter it starts uploading.

I am using Javascript and jQuery in client side.

Update: I was finally ended up with server side validation which reads bytes & rejects the upload if it is not an image.

Gumboil answered 20/11, 2010 at 19:37 Comment(3)
You're using Uploadify as suggested in one of your previous questions, right?Socialite
No, it stops in between 50-96. Tried many times with various inputs. And, i was also in a hurry for a solution at the time. So, i gave a try to simple jquery.ProgressBar.js. It works, fine. ### So, can i validate with uploadify!!!Gumboil
Can't we just simply use accept attribute in the input tag in order to make sure that the user selects the file of the specified format ?Kerrikerrie
S
132

It's possible to check only the file extension, but user can easily rename virus.exe to virus.jpg and "pass" the validation.

For what it's worth, here is the code to check file extension and abort if does not meet one of the valid extensions: (choose invalid file and try to submit to see the alert in action)

var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"];    
function Validate(oForm) {
    var arrInputs = oForm.getElementsByTagName("input");
    for (var i = 0; i < arrInputs.length; i++) {
        var oInput = arrInputs[i];
        if (oInput.type == "file") {
            var sFileName = oInput.value;
            if (sFileName.length > 0) {
                var blnValid = false;
                for (var j = 0; j < _validFileExtensions.length; j++) {
                    var sCurExtension = _validFileExtensions[j];
                    if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) {
                        blnValid = true;
                        break;
                    }
                }
                
                if (!blnValid) {
                    alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
                    return false;
                }
            }
        }
    }
  
    return true;
}
<form onsubmit="return Validate(this);">
  File: <input type="file" name="my file" /><br />
  <input type="submit" value="Submit" />
</form>

Note, the code will allow user to send without choosing file... if it's required, remove the line if (sFileName.length > 0) { and it's associate closing bracket. The code will validate any file input in the form, regardless of its name.

This can be done with jQuery in less lines, but I'm comfortable enough with "raw" JavaScript and the final result is the same.

In case you have more files, or want to trigger the check upon changing the file and not only in form submission, use such code instead:

var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"];    
function ValidateSingleInput(oInput) {
    if (oInput.type == "file") {
        var sFileName = oInput.value;
         if (sFileName.length > 0) {
            var blnValid = false;
            for (var j = 0; j < _validFileExtensions.length; j++) {
                var sCurExtension = _validFileExtensions[j];
                if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) {
                    blnValid = true;
                    break;
                }
            }
             
            if (!blnValid) {
                alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
                oInput.value = "";
                return false;
            }
        }
    }
    return true;
}
File 1: <input type="file" name="file1" onchange="ValidateSingleInput(this);" /><br />
File 2: <input type="file" name="file2" onchange="ValidateSingleInput(this);" /><br />
File 3: <input type="file" name="file3" onchange="ValidateSingleInput(this);" /><br />

This will show alert and reset the input in case of invalid file extension.

Styliform answered 21/11, 2010 at 9:17 Comment(6)
I'd just like to add that using "onSubmit" instead of "onChange" is cumbersome - especially if the "multiple" option is used. Each file should be checked as it selected, not when the entire form is posted.Honora
@Honora interesting idea, will mention this as well in the post. Thanks!Styliform
Thank you very much for this code @Shadow Wizard.It really helped me much!Iciness
@garryman fails how? The question here doesn't mention the file is required. If in your case the file is a required field, you can move the line var blnValid = false; to be above the loop over arrInputs, then after the loop check the variable blnValid: if true, let the form submit, otherwise show alert that the file is required.Styliform
check my below answerSkillless
@DivyeshJani why should I check your answer?Styliform
S
81

None of the existing answers seemed quite compact enough for the simplicity of the request. Checking if a given file input field has an extension from a set can be accomplished as follows:

function hasExtension(inputID, exts) {
    var fileName = document.getElementById(inputID).value;
    return (new RegExp('(' + exts.join('|').replace(/\./g, '\\.') + ')$')).test(fileName);
}

So example usage might be (where upload is the id of a file input):

if (!hasExtension('upload', ['.jpg', '.gif', '.png'])) {
    // ... block upload
}

Or as a jQuery plugin:

$.fn.hasExtension = function(exts) {
    return (new RegExp('(' + exts.join('|').replace(/\./g, '\\.') + ')$')).test($(this).val());
}

Example usage:

if (!$('#upload').hasExtension(['.jpg', '.png', '.gif'])) {
    // ... block upload
}

The .replace(/\./g, '\\.') is there to escape the dot for the regexp so that basic extensions can be passed in without the dots matching any character.

There's no error checking on these to keep them short, presumably if you use them you'll make sure the input exists first and the extensions array is valid!

Snyder answered 28/6, 2013 at 1:38 Comment(3)
Nice. Note that these scripts are case sensitive. To solve this you need to give RexExp the "i" modifier, for example: return (new RegExp('(' + exts.join('|').replace(/\./g, '\\.') + ')$', "i")).test(fileName);Skyeskyhigh
A bit difficult to read, but that means adding , "i" after end of regex string ()$'). This will add support for any casing in file name extension (.jpg, .JPG, .Jpg, etc...)Skyeskyhigh
Thank you, Tedd, would be better to have case-insensitive matching.Snyder
W
44
$(function () {
    $('input[type=file]').change(function () {
        var val = $(this).val().toLowerCase(),
            regex = new RegExp("(.*?)\.(docx|doc|pdf|xml|bmp|ppt|xls)$");

        if (!(regex.test(val))) {
            $(this).val('');
            alert('Please select correct file format');
        }
    });
});
Wera answered 18/3, 2015 at 6:43 Comment(3)
Thanks, very simple and clean.Ohmage
if you press cancel, it will trigger an alert.Malamut
If you have a "file" object, use file.name instead val(): var val = $(file.name).toLowerCase(), ...Rutaceous
P
22

I came here because I was sure none of the answers here were quite...poetic:

function checkextension() {
  var file = document.querySelector("#fUpload");
  if ( /\.(jpe?g|png|gif)$/i.test(file.files[0].name) === false ) { alert("not an image!"); }
}
<input type="file" id="fUpload" onchange="checkextension()"/>
Precocious answered 22/11, 2016 at 23:7 Comment(2)
Thanks this works in Angular with little modification, thanksDisaffect
worked well for me, though one should trim any trailing spaces from the name before testing. +1Incalculable
F
14

Do you use the input type="file" to choose the uploadfiles? if so, why not use the accept attribute?

<input type="file" name="myImage" accept="image/x-png,image/gif,image/jpeg" />
Foliose answered 7/9, 2018 at 14:21 Comment(2)
This! accept="image/*" it's definitely the smartest choice in most cases.Onrush
after clicking on browse button, in popup if we select all files than it will display all files, not only imagesSaragossa
T
10

check that if file is selected or not

       if (document.myform.elements["filefield"].value == "")
          {
             alert("You forgot to attach file!");
             document.myform.elements["filefield"].focus();
             return false;  
         }

check the file extension

  var res_field = document.myform.elements["filefield"].value;   
  var extension = res_field.substr(res_field.lastIndexOf('.') + 1).toLowerCase();
  var allowedExtensions = ['doc', 'docx', 'txt', 'pdf', 'rtf'];
  if (res_field.length > 0)
     {
          if (allowedExtensions.indexOf(extension) === -1) 
             {
               alert('Invalid file Format. Only ' + allowedExtensions.join(', ') + ' are allowed.');
               return false;
             }
    }
Tradeswoman answered 21/5, 2013 at 11:11 Comment(0)
G
8

I like this example:

<asp:FileUpload ID="fpImages" runat="server" title="maximum file size 1 MB or less" onChange="return validateFileExtension(this)" />

<script language="javascript" type="text/javascript">
    function ValidateFileUpload(Source, args) {
        var fuData = document.getElementById('<%= fpImages.ClientID %>');
        var FileUploadPath = fuData.value;

        if (FileUploadPath == '') {
            // There is no file selected 
            args.IsValid = false;
        }
        else {
            var Extension = FileUploadPath.substring(FileUploadPath.lastIndexOf('.') + 1).toLowerCase();
            if (Extension == "gif" || Extension == "png" || Extension == "bmp" || Extension == "jpeg") {
                args.IsValid = true; // Valid file type
                FileUploadPath == '';
            }
            else {
                args.IsValid = false; // Not valid file type
            }
        }
    }
</script>
Grallatorial answered 29/9, 2012 at 21:59 Comment(0)
L
7

Better to try with mimetype than checking extension. Because, sometimes files can be exist without it and those are working very well in linux or unix systems.

So, you can try something like this:

["image/jpeg", "image/png", "image/gif"].indexOf(file.type) > -1

or

["image/jpeg", "image/png", "image/gif"].includes(file.type)
Lurk answered 5/11, 2020 at 8:17 Comment(0)
T
6

If you're needing to test remote urls in an input field, you can try testing a simple regex with the types that you're interested in.

$input_field = $('.js-input-field-class');

if ( !(/\.(gif|jpg|jpeg|tiff|png)$/i).test( $input_field.val() )) {
  $('.error-message').text('This URL is not a valid image type. Please use a url with the known image types gif, jpg, jpeg, tiff or png.');
  return false;
}

This will capture anything ending in .gif, .jpg, .jpeg, .tiff or .png

I should note that some popular sites like Twitter append a size attribute to the end of their images. For instance, the following would fail this test even though it's a valid image type:

https://pbs.twimg.com/media/BrTuXT5CUAAtkZM.jpg:large

Because of that, this isn't a perfect solution. But it will get you to about 90% of the way.

Tole answered 30/6, 2014 at 4:59 Comment(0)
P
4

try this (Works for me)

  
  function validate(){
  var file= form.file.value;
       var reg = /(.*?)\.(jpg|bmp|jpeg|png)$/;
       if(!file.match(reg))
       {
    	   alert("Invalid File");
    	   return false;
       }
       }
<form name="form">
<input type="file" name="file"/>
<input type="submit" onClick="return validate();"/>
</form>

     
Phonetist answered 25/3, 2017 at 16:11 Comment(0)
I
2

You can use the accept attribute available for input file types. Checkout MDN documentation

Izettaizhevsk answered 6/5, 2017 at 7:26 Comment(2)
With this you can still select other file typesTrinh
@CésarLeón Yes. User has option to select all files. If you want restrict that also, you need to do manual validation. Check other answers.Deliadelian
B
2

When you want to validate browse button and file extension, use this code:

function fileValidate(){ 
var docVal=document.forms[0].fileUploaded.value;
var extension = docVal.substring(docVal.lastIndexOf(".")+1,docVal.length);
if(extension.toLowerCase() != 'pdf')
alert("Please enter file  in .pdf extension ");

return false;
}
Bradwell answered 24/4, 2019 at 7:13 Comment(1)
when you want to validate browse button and file extension,use this code.Bradwell
H
2

Another nowadays example via Array.prototype.some().

function isImage(icon) {
  const ext = ['.jpg', '.jpeg', '.bmp', '.gif', '.png', '.svg'];
  return ext.some(el => icon.endsWith(el));
}

console.log(isImage('questions_4234589.png'));
console.log(isImage('questions_4234589.doc'));
Hahn answered 11/8, 2020 at 8:41 Comment(0)
J
1

Here is a more reusable way, assuming you use jQuery

Library function (does not require jQuery):

function stringEndsWithValidExtension(stringToCheck, acceptableExtensionsArray, required) {
    if (required == false && stringToCheck.length == 0) { return true; }
    for (var i = 0; i < acceptableExtensionsArray.length; i++) {
        if (stringToCheck.toLowerCase().endsWith(acceptableExtensionsArray[i].toLowerCase())) { return true; }
    }
    return false;
}


String.prototype.startsWith = function (str) { return (this.match("^" + str) == str) }

String.prototype.endsWith = function (str) { return (this.match(str + "$") == str) }

Page function (requires jQuery (barely)):

$("[id*='btnSaveForm']").click(function () {
    if (!stringEndsWithValidExtension($("[id*='fileUploader']").val(), [".png", ".jpeg", ".jpg", ".bmp"], false)) {
        alert("Photo only allows file types of PNG, JPG and BMP.");
        return false;
    }
    return true;
});
Jagannath answered 7/8, 2012 at 18:59 Comment(0)
M
1

[TypeScript]

uploadFileAcceptFormats: string[] = ['image/jpeg', 'image/gif', 'image/png', 'image/svg+xml'];

// if you find the element type in the allowed types array, then read the file
isAccepted = this.uploadFileAcceptFormats.find(val => {
    return val === uploadedFileType;
});
Moser answered 29/3, 2017 at 10:51 Comment(0)
L
1

This is how it is done in jquery

$("#artifact_form").submit(function(){
    return ["jpg", "jpeg", "bmp", "gif", "png"].includes(/[^.]+$/.exec($("#artifact_file_name").val())[0])
  });
Larva answered 13/7, 2019 at 9:16 Comment(0)
S
1

we can check it on submit or we can make change event of that control

var fileInput = document.getElementById('file');
    var filePath = fileInput.value;
    var allowedExtensions = /(\.jpeg|\.JPEG|\.gif|\.GIF|\.png|\.PNG)$/;
    if (filePath != "" && !allowedExtensions.exec(filePath)) {
    alert('Invalid file extention pleasse select another file');
    fileInput.value = '';
    return false;
    }
Skillless answered 23/1, 2020 at 6:19 Comment(0)
W
1

using Array

Add all of your file-extensions/mimeType in validExtensions Array

const validExtensions = ["image/jpg", "image/jpeg", "image/png", "image/gif"];
const isValidExtension = validExtensions.indexOf(file.mimetype) > -1;
console.log(isValidExtension);
Wamsley answered 2/3, 2021 at 5:11 Comment(0)
C
0
<script type="text/javascript">

        function file_upload() {
            var imgpath = document.getElementById("<%=FileUpload1.ClientID %>").value;
            if (imgpath == "") {
                alert("Upload your Photo...");
                document.file.word.focus();
                return false;
            }
            else {
                // code to get File Extension..

                var arr1 = new Array;
                arr1 = imgpath.split("\\");
                var len = arr1.length;
                var img1 = arr1[len - 1];
                var filext = img1.substring(img1.lastIndexOf(".") + 1);
                // Checking Extension
                if (filext == "bmp" || filext == "gif" || filext == "png" || filext == "jpg" || filext == "jpeg" ) {
                    alert("Successfully Uploaded...")
                    return false;
                }
                else {
                    alert("Upload Photo with Extension ' bmp , gif, png , jpg , jpeg '");
                    document.form.word.focus();
                    return false;
                }
            }
        }

        function Doc_upload() {
            var imgpath = document.getElementById("<%=FileUpload2.ClientID %>").value;
            if (imgpath == "") {
                alert("Upload Agreement...");
                document.file.word.focus();
                return false;
            }
            else {
                // code to get File Extension..

                var arr1 = new Array;
                arr1 = imgpath.split("\\");
                var len = arr1.length;
                var img1 = arr1[len - 1];
                var filext = img1.substring(img1.lastIndexOf(".") + 1);
                // Checking Extension
                if (filext == "txt" || filext == "pdf" || filext == "doc") {
                    alert("Successfully Uploaded...")
                    return false;
                }
                else {
                    alert("Upload File with Extension ' txt , pdf , doc '");
                    document.form.word.focus();
                    return false;
                }
            }
        }
</script>
Colier answered 3/12, 2013 at 5:48 Comment(1)
It would be better if you write short description of your answer.Astrophysics
G
0

var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"];    
function ValidateSingleInput(oInput) {
    if (oInput.type == "file") {
        var sFileName = oInput.value;
         if (sFileName.length > 0) {
            var blnValid = false;
            for (var j = 0; j < _validFileExtensions.length; j++) {
                var sCurExtension = _validFileExtensions[j];
                if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) {
                    blnValid = true;
                    break;
                }
            }
             
            if (!blnValid) {
                alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
                oInput.value = "";
                return false;
            }
        }
    }
    return true;
}
File 1: <input type="file" name="file1" onchange="ValidateSingleInput(this);" /><br />
File 2: <input type="file" name="file2" onchange="ValidateSingleInput(this);" /><br />
File 3: <input type="file" name="file3" onchange="ValidateSingleInput(this);" /><br />
Gwinn answered 24/7, 2015 at 7:19 Comment(0)
N
0

You can create an array that includes the filetype that is needed and use $.inArray() in jQuery to check if filetype exist in array.

var imageType = ['jpeg', 'jpg', 'png', 'gif', 'bmp'];  

// Given that file is a file object and file.type is string 
// like "image/jpeg", "image/png", or "image/gif" and so on...

if (-1 == $.inArray(file.type.split('/')[1], imageType)) {
  console.log('Not an image type');
}
Negrophobe answered 20/11, 2015 at 6:5 Comment(0)
U
-1

This is the best solution in my opinion, which is by far much shorter than the other ones:

function OnSelect(e) {
    var acceptedFiles = [".jpg", ".jpeg", ".png", ".gif"];
    var isAcceptedImageFormat = ($.inArray(e.files[0].extension, acceptedFiles)) != -1;

    if (!isAcceptedImageFormat) {
        $('#warningMessage').show();
    }
    else {
        $('#warningMessage').hide();
    }
}

In this case, the function is called from a Kendo Upload control with this setting:

.Events(e => e.Select("OnSelect")).

Unzip answered 22/3, 2017 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.