4

I want a validation in Javascript that, a file name should be of specific type should be uploaded like for an example.

I have a fileupload control which has the feature to upload multipe file.

here is the html of that.

<asp:FileUpload runat="server" ID="flufileUpload" AllowMultiple="true" onchange="return ValidateFileType(this);" />

So while uploading i want user to upload file of specific name

like:-

A user can upload only 5 files with only name as

1 -> 120.jpg

2 -> 150.jpg

3 -> 180.jpg

4 -> 210.jpg

5 -> 240.jpg

if user uploads filename other than this then it should prompt alert message.

my function for handling some validations is below. but I am unable to handle the filename validation.

function ValidateFileType(controlName) {
    try {
        var uploadControl = controlName;
        var isCValidFile = false;

        for (var i = 0; i < uploadControl.files.length; i++) {
            isCValidFile = false;

            var path = uploadControl.files[i].name;
            var ext = path.substring(path.lastIndexOf(".") + 1, path.length).toLowerCase();

            if (path != "") {
                for (var j = 0; j < ValidImageFileExtension.length; j++) {
                    if (ext == ValidImageFileExtension[j]) {
                        isCValidFile = true;
                        break;
                    }
                }
                if (!isCValidFile) {
                    jAlert("Invalid File. Please upload a File with extension " + ValidImageFileExtension.join(", "), "Information");
                    uploadControl.value = '';
                    isCValidFile = false;
                    break;
                }
                else if (uploadControl.files[i].size > 15728640) {
                    jAlert("Please check file size should be less than 15 MB.", "Information");
                    uploadControl.value = '';
                    isCValidFile = false;
                    break;
                }
            }
            else {
                jAlert("Please select File", "Information");
                isCValidFile = false;
                break;
            }
        }

        return isCValidFile;

    } catch (e) {
        isCValidFile = false;
        jAlert("Error occurred on validate file.", "Error");
        return isCValidFile;
    }
}
wasmup
  • 14,541
  • 6
  • 42
  • 58
Nad
  • 4,605
  • 11
  • 71
  • 160
  • You've already got the loop going through the `files` array, so all you need to do is use [this code](https://stackoverflow.com/a/9234894/519413) to get the filename, then check if it matches any of your allowed values. – Rory McCrossan Jul 07 '17 at 10:07
  • @RoryMcCrossan: can u suggest how to bind those names in loop accordinlgy – Nad Jul 07 '17 at 10:59
  • @RoryMcCrossan: I m confused. please help – Nad Jul 07 '17 at 11:29
  • Do you want to make file name unique or just files has predtermined name? – Mehmet Otkun Jul 15 '17 at 02:09
  • @MehmetOtkun: The file has predetermined name. as I have given the name is specific – Nad Jul 17 '17 at 06:27

4 Answers4

3

You could check filenames with an object of valid file names and also you need to know which tab is active. you could use the following code

var Tabtype = document.getElementById('hdnType').value; 

if (Tabtype == "Panaromic") { 
    var validFileName = { 
         "120.jpg": 1, "150.jpg": 1, "180.jpg": 1, "210.jpg": 1, "240.jpg": 1, 
    } 
} 

if (Tabtype == "Satellite") { 
    var validFileName = { 
          "55.jpg": 1, "74.jpg": 1, "83.jpg": 1, "935.jpg": 1, 
    } 
} 

if (Tabtype == "SitePlot") { 
    var validFileName = 0; 
}


if (path != "") {
   if(validFileName && !isFileNameValid(path)){
       jAlert("Invalid File. Please upload a File with extension " + 
       ValidImageFileExtension.join(", "), "Information");
       uploadControl.value = '';
       isCValidFile = false;
       break;
   }
   ...
fingerpich
  • 8,500
  • 2
  • 22
  • 32
  • use `catch (e) { console.log(e);` to find problem – fingerpich Jul 10 '17 at 05:54
  • getting error as `Unable to get property 'split' of undefined or null reference` – Nad Jul 10 '17 at 05:56
  • using google chrome inspector add break point at where you get `path` variable and check why it will be null or undefined – fingerpich Jul 10 '17 at 06:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/148752/discussion-between-vvvv-and-fingerpich). – Nad Jul 10 '17 at 06:07
  • You can remove that loop , because you have checked both filename and extension in the function – fingerpich Jul 11 '17 at 07:09
  • hey, need one small help here. I want to validate, like its mandatory to select 5 files for `panaromic` so if he selects 1 file and click on upload button it should fire validation message. if u want to discuss come on chat http://chat.stackoverflow.com/rooms/148752/discussion-between-vvvv-and-fingerpich – Nad Jul 21 '17 at 05:01
2

In practice, I would do one of two things here. Either write custom adapters for the jQuery Validation plugin or write a custom jQuery plugin.

I typically use jQuery validation so I would write custom adapters for my needs. This is beneficial because once written I can reuse the rules over and over and can configure them by changing attributes on my Html Elements. It also has the benefit of dynamically displaying error messages and disabling form submission without the need for my interaction.

Here's a working example of using Jquery Validation:

$(document).ready(function() {
  $.validator.addMethod("filecount", function(value, element, params) {
    var maxcount = params;
    if (maxcount) {
      return $(element)[0].files.length <= Number(maxcount);
    }
    return true;
  }, "Maximum number of files exceeded");

  $.validator.addMethod("filename", function(value, element, params) {

    if (!params) return true;
    var names = params.split(',');
    var files = $(element)[0].files;
    for (var i = 0; i < files.length; i++) {
      var file = files[i];
      if (names.indexOf(file.name.toLowerCase()) == -1) return false;
    }
    return true;

  }, "File name is not allowed");

  var mb = 1048576;
  var defaultmaxfilesize = mb * 15;

  $.validator.addMethod("filesize", function(value, element, params) {
    var el = $(element);
    var parsedmaxval = parseInt(el.attr("data-val-filesize-max"));
    var maxval = null;
    if (isNaN(parsedmaxval) || parsedmaxval < 1 || parsedmaxval > 1048576000) {
      maxval = defaultmaxfilesize;
    } else {

      maxval = parsedmaxval;
    }

    var files = el[0].files;
    if (files != null && files.length > 0) {
      for (var i = 0; i < files.length; i++) {
        var file = files[i];
        var size = file.size;
        if (maxval < Number(size)) return false;
      }
    }
    return true;

  }, "File is too large");
});
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <title></title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.16.0/jquery.validate.min.js"></script>



  <script>
    $(document).ready(function() {

      $('input[type="file"]').change(function() {

        var el = $(this);

        if (!el.valid()) el.val('');
      });
    });
  </script>
</head>

<body>
  <form id="form1" name="form1" action="/root" method="Post">
    <div>
      <input type=file 
          ID="flufileUpload" 
          multiple 
          data-msg-filename="File name must be '120.jpg, 150.jpg, 180.jpg, 210.jpg, or 240.jpg'" 
          data-rule-filename="120.jpg,150.jpg,180.jpg,210.jpg,240.jpg" 
          data-msg-filesize="Maximum File Size is 15 MB" 
          data-rule-filesize="15728640"
          data-msg-filecount="You can only upload 5 files" 
          data-rule-filecount="5" />


    </div>
    <div>
      <input type=file 
          ID="flufileUpload2" 
          name="flufileUpload2" 
          multiple 
          data-msg-filename="File name must be '480.jpg, 640.jpg, or 1024.jpg'" 
          data-rule-filename="480.jpg,640.jpg,1024.jpg" 
          data-msg-filesize="Maximum File Size is 10 MB" 
          data-rule-filesize="10485760"
          data-msg-filecount="You can only upload 5 files" 
          data-rule-filecount="5" />
    </div>
  </form>
</body>

</html>

When working in MVC, I use jQuery Unobtrusive Validation adapters which have a slightly different api and for this question might look like this:

$.validator.unobtrusive.adapters.add("filecount", ["filecount"], function (options) {
    options.rules["filecount"] = "#" + options.params.param;
    options.messages["filecount"] = options.message;
});

$.validator.addMethod("filecount", function (value, element, params) {

    var maxcount = $(element).attr("data-val-filecount-max");
    if (maxcount) {
        return $(element)[0].files.length <= Number(maxcount);
    }
    return true;

});
$.validator.unobtrusive.adapters.add("filenames", ["filename"], function (options) {
    options.rules["filename"] = "#" + options.params.param;
    options.messages["filename"] = options.message;
});

$.validator.addMethod("filename", function (value, element, params) {

    var names = $(element).attr("data-val-filename-allowed").split(',');
    var files = $(element)[0].files;
    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        if (names.indexOf(file.name.toLowerCase()) == -1) return false;
    }
    return true;

});

var mb = 1048576;
var defaultmaxfilesize = mb * 15;

$.validator.unobtrusive.adapters.add("filesize", ["filesize"], function (options) {
    options.rules["filesize"] = "#" + options.params.param;
    options.messages["filesize"] = options.message;
});

$.validator.addMethod("filesize", function (value, element, params) {
    var el = $(element);
    var parsedmaxval = parseInt(el.attr("data-val-filesize-max"));
    var maxval = null;
    if (isNaN(parsedmaxval) || parsedmaxval < 1 || parsedmaxval > 1048576000) {
        maxval = defaultmaxfilesize;
    } else {

        maxval = parsedmaxval;
    }

    var files = el[0].files;
    if (files != null && files.length > 0) {
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            var size = file.size;
            if (maxval < size) return false;
        }
    }
    return true;


});

I can then decorate my element with the validation attributes as required:

<input 
    type=file 
    ID="flufileUpload" 
    multiple data-val-filename="File name must be '120.jpg, 150.jpg, 180.jpg, 210.jpg, or 240.jpg'" 
    data-val-filename-allowed="120.jpg,150.jpg,180.jpg,210.jpg,240.jpg"
    data-val-filesize="Maximum File Size is 15 MB"
    data-val-filesize-max="15728640"
    data-val-filecount="You can only upload 5 files"
    data-val-filecount-max="5"
/>

And using different values for a different element is just a matter of changing the attributes:

<input 
    type=file 
    ID="flufileUpload" 
    multiple data-val-filename="File name must be '480.jpg, 640.jpg, or 1024.jpg'" 
    data-val-filename-allowed="480.jpg,640.jpg,1024.jpg"
    data-val-filesize="Maximum File Size is 10 MB"
    data-val-filesize-max="10485760"
/>

The other approach I would take is creating a custom jQuery plugin. This allows for custom functions that can be configured by passing options to the the plugin. I would typically only take this approach if I need custom functionality, such as automatically uploading the files after they passed validation using AJAX or if granular control of the error messages was needed.

Once written your plugin can be called with custom options as needed like this:

 <script>
        $(document).ready(function () {
            $('#flufileUpload').fileValidate({ maxcount: 5, allowedFileNames: "file1.html,file2.html,file3.html" });
        });
    </script>

A custom plugin would look like this, but typically you would put the plugin JavaScript in its own file so you can reuse it as needed:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
        #qrcode {
            width: 160px;
            height: 160px;
            margin-top: 15px;
        }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script>
        (function ($) {
            $.fn.fileValidate = function (options) {
                var Container = $(this);
                var id = Container.attr("id");
                var mb = 1048576;
                var settings = $.extend({
                    maxfilesize: mb * 15,
                    allowMultiple: true,
                    allowedFileNames: null,
                    allowedExtensions: ".png,.gif,tif,.tiff,.jpg,.jpeg,.bmp,.pdf",
                    maxcount: -1,
                    documentRemoveCallback: null,
                    target: null,
                    errlab: null
                }, options);

                var getErrorLabel = function () {
                    var validator = $('span[data-val-msgfor="' + id + "']");
                    if (validator.length == 0) {
                        validator = $("<span/>");
                        validator.attr("data-val-msgfor", id);
                        Container.parent().append(validator);
                    }
                    return validator;
                }
                var formatBytes = function formatBytes(bytes, decimals) {
                    if (bytes == 0) return '0 Bytes';
                    var k = 1024,
                        dm = decimals + 1 || 3,
                        sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
                        i = Math.floor(Math.log(bytes) / Math.log(k));
                    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
                };
                var validExtensions = (settings.allowedExtensions) ? settings.allowedExtensions.split(",") : [];
                var validFileNames = (settings.allowedFileNames) ? settings.allowedFileNames.split(",") : [];
                var errlab = settings.errlab || getErrorLabel();
                var hasError = false;
                var errors = [];
                var setError = function (s) {
                    errors.push(s);

                }
                var getErrorHtml = function () {
                    var ul = $("<ul>");
                    errors.forEach(function (err) { ul.append($("<li>").html(err)); });
                    return ul;
                }
                var validateSize = function (files) {
                    for (var i = 0; i < files.length; i++) {
                        if (files[i].size > settings.maxfilesize) return false;
                    }
                    return true;
                }
                var validateExenstions = function (files) {
                    var invalid = [];
                    for (var i = 0; i < files.length; i++) {
                        var file = files[i];
                        var parts = file.name.split(".");
                        var ext = parts[parts.length - 1].toLowerCase();
                        var found = false;
                        validExtensions.forEach(function (x) {
                            if (x == ext) found = true;
                        });
                        !found && invalid.indexOf(ext) == -1 && invalid.push(ext);
                        if (!found) return false;
                    }
                    return true;

                }
                var validateFileNames = function (files) {
                    for (var i = 0; i < files.length; i++) {
                        var file = files[i];
                        if (validFileNames.indexOf(file.name) == -1) return false;
                    }
                    return true;
                }
                var onDocumentChange = function () {
                    errors = [];
                    var el = Container[0];
                    errlab.html('');
                    var files = el.files;

                    settings.maxcount > 0 && files.length > settings.maxcount && setError("You may only select " + settings.maxcount + " file(s).");
                    validExtensions.length > 0 && !validateExenstions(files) && setError("File extensions must be '" + settings.allowedExtensions + "'.");
                    settings.maxfilesize > 0 && !validateSize(files) && setError("Maximum file size is " + formatBytes(settings.maxfilesize) + ".");
                    validFileNames.length > 0 && !validateFileNames(files) && setError("Files names must be one of the following: '" + settings.allowedFileNames + "'.");
                    errors.length > 0 && $(Container).val(''), errlab.html('').append(getErrorHtml());
                    if (settings.documentChangeCallBack) { window.setTimeout(settings.documentChangeCallBack, 1); }
                };
                Container.change(onDocumentChange);
            };
        }(jQuery));
    </script>
</head>
<body>




    <input type=file ID="flufileUpload" multiple />
    <script>
      
    </script>
    <script>
        $(document).ready(function () {
            $('#flufileUpload').fileValidate({ maxcount: 5, allowedFileNames: "file1.html,file2.html,file3.html" });
        });
    </script>

</body>
</html>
Alexander Higgins
  • 6,765
  • 1
  • 23
  • 41
1

copy paste below code in sample html. hope it is working as you r expecting.

<!DOCTYPE html>
    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
      <title></title>
    </head>
    <body>  
      <label for="file">Filename:</label>
        <input type="file" name="filename" id="filename" onchange="ValidateFileType();" multiple="multiple"/> 
    </body>


<script>
function ValidateFileType() {

var ext_names = ["jpg", "png", "jpeg"];

    try {
        var uploadControl = document.getElementById('filename');
        var isCValidFile = false;

        for (var i = 0; i < uploadControl.files.length; i++) {
            isCValidFile = false;
            var path = uploadControl.files[i].name;
            var ext = path.substring(path.lastIndexOf(".") + 1, path.length).toLowerCase();
            alert(path);
            if (path != "") {

            alert(ext);
                    if (ext_names.indexOf(ext) > -1) {
                        isCValidFile = true;    
                       // break;
                    }

                if (!isCValidFile) {
                    alert("Invalid File. Please upload a File with extension " + ext_names.join(", "), "Information");
                    uploadControl.value = '';
                    isCValidFile = false;
                    break;
                }
                else if (uploadControl.files[i].size > 15728640) {
                    alert("Please check file size should be less than 15 MB.", "Information");
                    uploadControl.value = '';
                    isCValidFile = false;
                    break;
                }
            }
            else {
                alert("Please select File", "Information");
                isCValidFile = false;
                break;
            }
        }

        return isCValidFile;

    } catch (e) {
        isCValidFile = false;
        alert("Error occurred on validate file.", "Error");
        return isCValidFile;
    }
}
</script>


    </html>

Try this code...

1

If you want to just validate specific file name it is easy. No need for checking extension. However if you want to make file name unique, you can do on back-end.

function ValidateFileType(controlName) {
  try {
       var uploadControl = controlName;
       var isCValidFile = false;
       var validFileNames = ["120.jpg","150.jpg","180.jpg","210.jpg","240.jpg"]

       for (var i = 0; i < uploadControl.files.length; i++) {
           var file = uploadControl.files[i];
           var fileName = file.name.split(/(\\|\/)/g).pop().toLowerCase();
           if (validFileNames.indexOf(fileName) < 0) {
              jAlert("Invalid file name, please select etc...",  "Information");
           }
           else if (file.size > 15728640) {
                   jAlert("Please check file size should be less than 15 MB.",  "Information");
           }
           else {
               isCValidFile = true;
           }

           if(!isCValidFile)
               uploadControl.value = '';
       }

       return isCValidFile;

   } catch (e) {
       uploadControl.value = '';
       jAlert("Error occurred on validate file.", "Error");
       return false;
   }
}
Mehmet Otkun
  • 1,374
  • 9
  • 22