31

I have the form having the follwing fields,

<form onsubmit="return checkcreateform()" action="/gallery/create" method="post" enctype="multipart/form-data">
   <label>Type:*</label>
    <label for="type-1">
     <input type="radio" checked="checked" value="1" id="type-1" name="type">Image
    </label>
   <br>
   <label for="type-2">
   <input type="radio" value="2" id="type-2" name="type">Video
   </label>  
   <label class="itemdetailfloatL required" for="file">File:*</label>
   <input type="hidden" id="MAX_FILE_SIZE" value="8388608" name="MAX_FILE_SIZE">
   <input type="file" tabindex="5" class="text-size text" id="file" name="file">
 <input type="submit" value="Create" id="submit" name="submit">
</form>

I want to validate before form submit. Here how can i validate if user select type as Image and upload video or select type as video and upload image ?

We can achieve this by javascript or jquery.Any quick way to validate this ?

Kindly help me on this.

mymotherland
  • 7,968
  • 14
  • 65
  • 122
  • 1
    I use jQuery Validation plugin: http://bassistance.de/jquery-plugins/jquery-plugin-validation/ – Wayne Nov 02 '11 at 07:53
  • 2
    There is an "accept" attribute coming soon, it's not really supported yet, but have a look : http://www.w3schools.com/jsref/prop_fileupload_accept.asp Normally the only secure and effective way to do this would be serverside, but you could just check for file extensions with javascript or jQuery's validate plugin. – adeneo Nov 02 '11 at 07:55
  • 1
    @adeneo 10 years later...this proved to be the easiest way to upload the alllowed file. Thanks :) – Amresh Giri Jul 22 '21 at 09:20

7 Answers7

66

Instead of using onsubmit, use jQuery's submit handler, and validate using some javascript like the following:

function getExtension(filename) {
  var parts = filename.split('.');
  return parts[parts.length - 1];
}

function isImage(filename) {
  var ext = getExtension(filename);
  switch (ext.toLowerCase()) {
    case 'jpg':
    case 'gif':
    case 'bmp':
    case 'png':
      //etc
      return true;
  }
  return false;
}

function isVideo(filename) {
  var ext = getExtension(filename);
  switch (ext.toLowerCase()) {
    case 'm4v':
    case 'avi':
    case 'mpg':
    case 'mp4':
      // etc
      return true;
  }
  return false;
}

$(function() {
  $('form').submit(function() {
    function failValidation(msg) {
      alert(msg); // just an alert for now but you can spice this up later
      return false;
    }

    var file = $('#file');
    var imageChosen = $('#type-1').is(':checked');
    if (imageChosen && !isImage(file.val())) {
      return failValidation('Please select a valid image');
    } else if (!imageChosen && !isVideo(file.val())) {
      return failValidation('Please select a valid video file.');
    }

    // success at this point
    // indicate success with alert for now
    alert('Valid file! Here is where you would return true to allow the form to submit normally.');
    return false; // prevent form submitting anyway - remove this in your environment
  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="/gallery/create" method="post" enctype="multipart/form-data">
  <label>Type:*</label>
  <label for="type-1">
     <input type="radio" checked="checked" value="1" id="type-1" name="type">Image
    </label>
  <label for="type-2">
   <input type="radio" value="2" id="type-2" name="type">Video
    </label> <br />
  <label class="itemdetailfloatL required" for="file">File:*</label>
  <input type="hidden" id="MAX_FILE_SIZE" value="8388608" name="MAX_FILE_SIZE">
  <input type="file" tabindex="5" class="text-size text" id="file" name="file">
  <br/>
  <input type="submit" value="Create" id="submit" name="submit">
</form>

tested in IE8, RockMelt (based on Chrome) and Firefox 7: http://jsfiddle.net/Ngrbj/4/

dota2pro
  • 7,220
  • 7
  • 44
  • 79
GregL
  • 37,147
  • 8
  • 62
  • 67
  • 6
    user can easily change the file extension to "fool" such validation, a solution based on mimetype would be better (though, I'm not sure if such exists, still looking for it myself) – ioleo Feb 02 '13 at 12:33
  • see http://stackoverflow.com/questions/7395548/js-and-type-match-as-file-mime-type-need-advice – ioleo Feb 02 '13 at 12:41
  • 7
    getExtension can be one line by making it "return filename.split('.').pop();" – Ash Blue Aug 23 '13 at 20:20
  • 1
    one can easily change the file extension and pass through this – Kakar Jul 13 '15 at 20:17
  • @Kakar Correct. This is not fool-proof. This answer was written prior to having access to the File API to read the contents of files (which is still not an option if you have to support old browsers). No matter what JS solution you use, you would still want to verify it on the server as well. No client side validation ever replaces server side validation. – GregL Jul 14 '15 at 00:02
  • you can change the `getExtension(filename)` to one liner `return filename.split('.').pop()` or better if `return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;` – Muhammad Omer Aslam May 04 '18 at 00:42
  • @loostro mimetype can still get fooled just by changing an extension – adam rowe Jul 10 '18 at 20:34
26

Every File type has a 'type' property, for example: 'image/jpeg', 'audio/mp3' and so on... (this file-type format is called 'MIME types')

This is an example of one way to check the type of the file by using the 'match' method :

function getFileType(file) {

  if(file.type.match('image.*'))
    return 'image';

  if(file.type.match('video.*'))
    return 'video';

  if(file.type.match('audio.*'))
    return 'audio';

  // etc...

  return 'other';
}

match() works using regular expressions (regex) ; see an explanation here : https://regexr.com/7hrs8

You can also write it the boolean way:

function isImage(

  return !!file.type.match('image.*');

}
Silloky
  • 147
  • 13
Moshe Kohavi
  • 387
  • 3
  • 8
9

The answer provided works, but something that will run a little faster with a lot fewer lines for the validation code, using javascript array functions:

var extensionLists = {}; //Create an object for all extension lists
extensionLists.video = ['m4v', 'avi','mpg','mp4', 'webm'];  
extensionLists.image = ['jpg', 'gif', 'bmp', 'png'];

// One validation function for all file types    
function isValidFileType(fName, fType) {
    return extensionLists[fType].indexOf(fName.split('.').pop()) > -1;
}

Then, the if statement in the submit code is just swapped with:

if (imageChosen && !isValidFileType(file.val(), 'image')) {
        return failValidation('Please select a valid image');
    }
else if (!imageChosen && !isValidFileType(file.val(), 'video')) {
        return failValidation('Please select a valid video file.');
    }        
Gabriel Garrett
  • 2,087
  • 6
  • 27
  • 45
Wayne F. Kaskie
  • 3,257
  • 5
  • 33
  • 43
4

Using files property on input:file you can loop through file objects and check type property

    $('#upload').on("change", function(){
 
         var  sel_files  = document.getElementById('upload').files;
         var len = sel_files.length;
 
         for (var i = 0; i < len; i++) {

            var file = sel_files[i];
         
            if (!(file.type==='application/pdf')) {
            continue;
            }
          }

      }); 
<div class="modal">
  <form id="form-upload">
    <input type="file" name="upload" id="upload" multiple>
    <br/>
     
</form>
</div>
2

As already said, a file has a type property. You could compare the file type to a list of supported types like this:

const validFileTypes = ['image/jpeg', 'image/jpg', 'image/png'];

const fileTypeValid = (file, fileTypes) => {     
    return fileTypes.some((fileType) => fileType === file.type);
}

// ... call fileTypeValid with the two parameters
alex351
  • 1,826
  • 1
  • 21
  • 32
0

you can try this:

function getFile(fieldId) {
    var fileInsert = document.getElementById(fieldId).value;
        fileName = fileName.split('/');
        fileName = fileName[fileName.length];
        extentions = fileName.split('.');
        extentions = extentions[extentions.length];
    return extentions;
}

You can use this function in your checkcreateform()

Yoram de Langen
  • 5,391
  • 3
  • 24
  • 31
0

First you should change your html like this:

<input type="file" tabindex="5" class="text-size text" id="file" name="file" onchange="checkeExtension(this.value,"submit");">

Then, you need a function like this:

///image 1 and video 2
//you can extend file types
var types= {
    'jpg' :"1",
    'avi' :"2",
    'png' :"1",
    "mov" : "2",
}

function checkeExtension(filename,submitId) {
    var re = /\..+$/;
    var ext = filename.match(re);
    var type = $("input[type='radio']:checked").val();
    var submitEl = document.getElementById(submitId);

    if (types[ext] == type) {
        submitEl.disabled = false;
        return true;
    } else {
        alert("Invalid file type, please select another file");
        submitEl.disabled = true;
        return false;
    }  
}
Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
erimerturk
  • 4,230
  • 25
  • 25