43

Newbie here. The problem is that I currently have written a method which checks uploaded file size and extension in order to validate it. However, checking extensions is not a solution as that kind of validation may cause a lot of problems. What I want to do is to check the actual file type and validate it without using extension method. I have tried to use jQuery file validator but to no avail... This is a snippet from my current code:

<input type='file' id='imageLoader' name='imageLoader' accept="image/*" data-type='image' />

Script:

App.Dispatcher.on("uploadpic", function() {         
        $(":file").change(function() {
            if (this.files && this.files[0] && this.files[0].name.match(/\.(jpg|jpeg|png|gif)$/) ) {
                if(this.files[0].size>1048576) {
                    alert('File size is larger than 1MB!');
                }
                else {
                    var reader = new FileReader();
                    reader.onload = imageIsLoaded;
                    reader.readAsDataURL(this.files[0]);
                }
            } else alert('This is not an image file!');
        });
        function imageIsLoaded(e) {
            result = e.target.result;
            $('#image').attr('src', result);
        };
    });

It is called once the upload input changes and after validation it uploads and displays the image. For now, I only care about validation and any help or ideas would be greatly appreciated!

Acallar
  • 453
  • 1
  • 5
  • 5

10 Answers10

86

Try something like this:

JavaScript

const file = this.files[0];
const  fileType = file['type'];
const validImageTypes = ['image/gif', 'image/jpeg', 'image/png'];
if (!validImageTypes.includes(fileType)) {
    // invalid file type code goes here.
}

jQuery

var file = this.files[0];
var fileType = file["type"];
var validImageTypes = ["image/gif", "image/jpeg", "image/png"];
if ($.inArray(fileType, validImageTypes) < 0) {
     // invalid file type code goes here.
}
Raja Rama Mohan Thavalam
  • 8,131
  • 2
  • 31
  • 30
Hoyen
  • 2,511
  • 1
  • 12
  • 13
  • 1
    God, why I haven't thought about this? So simple, yet works perefectly, thank you! – Acallar Apr 23 '15 at 07:28
  • 10
    You shouldn't use capital letters to start a variable's name in Javascript. – Yonn Trimoreau Mar 08 '16 at 15:46
  • When I tried the same for docx extension files then file type is empty. Can you tell why it is and how I can check this ? – Varinder Nov 28 '16 at 14:03
  • @Varinder may be you can post a question on what you tried? This should be able to work with Microsoft Word documents as well. – Hoyen Nov 28 '16 at 14:26
  • Don't forget image/svg+xml – rboarman Nov 27 '18 at 21:51
  • 5
    This answer isn't right. If you change the extension of a file to, for example, .png or .jpg, you will always get a valid image file, even if your file is a pdf, txt or something not related with an image. Check @sujit answer or [this](https://stackoverflow.com/questions/32222786/file-upload-check-if-valid-image) for a valid solution – bruno.almeida Nov 28 '18 at 15:09
  • In the documentation it is at bold this: "Developers are advised not to rely on this property as a sole validation scheme." https://developer.mozilla.org/docs/Web/API/File/type#Example. – bruno.almeida Nov 28 '18 at 15:18
41

You don't need jquery here.

var mimeType=this.files[0]['type'];//mimeType=image/jpeg or application/pdf etc...


//ie image/jpeg will be ['image','jpeg'] and we keep the first value
    if(mimeType.split('/')[0] === 'image'){
       console.log('the file is image');
    }

You can also create a function to check when a file is image.

function isImage(file){
   return file['type'].split('/')[0]=='image');//returns true or false
}

 isImage(this.file[0]);

Update (es6)

using es6 includes method, makes it even more simple.

const isImage = (file) => file['type'].includes('image');
Mike Antoniadis
  • 657
  • 7
  • 12
11

Pls refer a related query here. The answer here suggests to load the image in an Image object and check for it's width and height properties to be non zero. I think the technique can be used to solve your problem too.

I also worked out a fiddle for you to refer. Pertinent code below:

var img = new Image();
img.addEventListener("load",function(){
  alert('success');
});
img.addEventListener("error",function(){
      alert('error');
});
  img.src = picFile.result; 
Community
  • 1
  • 1
sujit
  • 2,258
  • 1
  • 15
  • 24
  • This should be the accepted answer. Other answers user `file.type`, that only have the information of the file extension. For more information check https://developer.mozilla.org/docs/Web/API/File/type#Example – bruno.almeida Nov 28 '18 at 15:17
7

Here is a quick tip if you just want to know if the file is an image:

var file = this.files[0];
var fileType = file["type"];

if (fileType.search('image') >= 0) {
  ...
}
romerompb
  • 860
  • 11
  • 15
4

What I want to do is to check the actual file type

Try accessing files[0].type property . See Using files from web applications

$(":file").on("change", function(e) {

  console.log(this.files[0].type);
  
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type='file' id='imageLoader' name='imageLoader' accept="image/*" data-type='image' />
guest271314
  • 1
  • 15
  • 104
  • 177
  • Somehow I managed to miss this .type thingy, no sophisticated methods are needed, this works great, thank you (: – Acallar Apr 23 '15 at 07:29
  • 1
    Just curious. As per your original question "However, checking extensions is not a solution as that kind of validation may cause a lot of problems. What I want to do is to check the actual file type": - Want to check whether the type attribute really returns anything other than checking the extension internally. Since, while I was attempting to answer the OP, i found that when i renamed a text file to a.png and uploaded it, the type attribute check for image was a success even though the actual file wasn't one. – sujit Apr 24 '15 at 04:39
2

If anyone comes here who is using jQuery Validator, a simple method would be:

jQuery.validator.addMethod(
    "onlyimages",
    function (value, element) {
        if (this.optional(element) || !element.files || !element.files[0]) {
            return true;
        } else {
            var fileType = element.files[0].type;
            var isImage = /^(image)\//i.test(fileType);
            return isImage;
        }
    },
    'Sorry, we can only accept image files.'
);

which is then added to the .validate() function.

Neil Thompson
  • 6,356
  • 2
  • 30
  • 53
2

A lot of convoluted answers here. Simply check whether the file has an image mime-type (which would be of the format image/...

const isImage = file => file.type.startsWith("image/")
Tobiq
  • 2,489
  • 19
  • 38
1
$('#direct_upload').change(function() {

      if (this.files[0].type.includes('image')) {
        document.getElementById('attach_file').src = window.URL.createObjectURL(this.files[0])
      } else {
        console.log('it is a doc');
      }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
0

You could try to convert file type in string and after that slice this string like that:

if(String(file.type).slice(0, 6) === 'image/') {....some code}
Oleg Sevruk
  • 999
  • 8
  • 11
0

Using jQuery version 3.3.1:

<!DOCTYPE html>
<html>

<head>
  <title>Page Title</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <label class="custom-file-label" for="customFile">Select Image</label>
  <br>
  <input type="file" class="custom-file-input" id="customFile">
</body>

<script>
  $(document).ready(function() {
    $(document).on("change", ".custom-file-input", function() {
      var myImg = this.files[0];
      var myImgType = myImg["type"];
      var validImgTypes = ["image/gif", "image/jpeg", "image/png"];

      if ($.inArray(myImgType, validImgTypes) < 0) {
        alert("Not an image")
      } else {
        alert("Is an image")
      }

    });
  });
</script>

</html>
VillageSavers
  • 41
  • 1
  • 6