用于文件类型的jQuery不显眼的验证错误消息

时间:2016-08-09 12:23:48

标签: jquery asp.net-mvc validation unobtrusive-validation

我有一个MVC项目,我只使用标记来使用jquery不显眼的验证。困扰我的一件事是错误文件mime类型的验证消息。

以下是正常文本输入的示例,其中包含我正在使用的一些验证:

<input class="form-control valid" data-val="true" data-val-regex="not correct regex message." data-val-regex-pattern="^.{0,440}$" id="field1" name="field1" placeholder="max 440 characters" type="text" value="">

输入已经简化。但这基本上就是我如何使用它,纯粹是用#34;数据 - &#34;属性。

但是我不知道的是文件上传。我添加了&#34; additional-methods.js&#34;文件,&#34;接受&#34;使用相应的消息正确验证属性:

<input accept="image/jpeg,image/pjpeg,image/png,image/bmp,image/x-windows-bmp,image/x-ms-bmp" class="dynamicDocumentFileUpload" data-val="true" data-val-required="this is required" id="field2" name="field2" placeholder="file input field" title="upload picture" type="file" value="">

因此需要按预期工作,如果我尝试上传不正确的mime类型的文件,则验证会按预期阻止表单提交。 但!它只是在&#34; @Html.ValidationMessageFor&#34;中显示输入的名称。我不知道什么数据属性对应于&#34;接受&#34;验证

我试过这个:

@Html.ValidationMessageFor(m => Model.Groups[g].Fields[f].File, "wrong file type")

但无论错误类型如何,当然都会显示该消息。

1 个答案:

答案 0 :(得分:0)

在MVC(模型视图控制器)中进行开发时避免使用模型不是一个好主意。正如MVC的意思所说,大多数时候你应该在使用IsValid方法在数据库中保存数据之前验证你的模型。我能给你的建议是忘记你的工作方式,因为它不安全。如果不使用模型的无效方法,您是否可以保护您的网站免受XSS脚本和其他类型的攻击。模型的主要优点是您可以在保存这些数据之前轻松验证它,并且您可以通过创建自己的验证属性轻松解决此类问题,该属性将在服务器端和客户端检查这些数据。忘记你正在做的事情,并尝试了解自定义验证。但是,我可以共享此代码,如果您使用的是模型,它将检查服务器中的文件类型。

     public class FileTypeAttribute : ValidationAttribute
{
    public string thefile{ get; set; }
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        PropertyInfo[] propriétés = validationContext.ObjectType.GetProperties();
        PropertyInfo lafichies = propriétés.FirstOrDefault(p => p.Name == lefichier);

        HttpPostedFileBase valFichierChoisi = thefile.GetValue(validationContext.ObjectInstance, null) as HttpPostedFileBase;
        byte[] chkBytejpg = { 255, 216, 255, 224 };
        byte[] chkBytejpg2 = { 255, 216, 255, 225 };

        if (value != null && value.Equals(valFichierChoisi))
        {//we check the type for jpeg file
            //-------------------------------------------
            if (valFichierChoisi.ContentType.ToLower() != "image/jpg" &&
                        valFichierChoisi.ContentType.ToLower() != "image/jpeg" &&
                        valFichierChoisi.ContentType.ToLower() != "image/pjpeg")

            {
                return new ValidationResult(ErrorMessage);
            }


            //  Attempt to read the file and check the first bytes
            //-------------------------------------------
            try
            {
                if (!valFichierChoisi.InputStream.CanRead)
                {
                    return new ValidationResult(ErrorMessage);
                }

                if (valFichierChoisi.ContentLength < ImageMinimumBytes)
                {
                    return new ValidationResult(ErrorMessage);
                }

                byte[] buffer = new byte[valFichierChoisi.ContentLength];
                valFichierChoisi.InputStream.Read(buffer, 0, valFichierChoisi.ContentLength);
                string content = System.Text.Encoding.UTF8.GetString(buffer);
                if (Regex.IsMatch(content, @"<script|<html|<head|<title|<body|<pre|<table|<a\s+href|<img|<plaintext|<cross\-domain\-policy",
                    RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Multiline))
                {
                    return new ValidationResult(ErrorMessage);
                }
                //you compare buffer sequence of file and known byte of jpeg in .net
                if (chkBytejpg.SequenceEqual(buffer.Take(chkBytejpg.Length)))
                {
                    return ValidationResult.Success;
                }

                else if (chkBytejpg2.SequenceEqual(buffer.Take(chkBytejpg2.Length)))
                {
                    return ValidationResult.Success;
                }

            }
            catch (Exception)
            {
                return new ValidationResult(ErrorMessage);
            }

            //-------------------------------------------
            //  Try to instantiate new Bitmap, if .NET will throw exception
            //  we can assume that it's not a valid image
            //-------------------------------------------

            try
            {
                using (var bitmap = new System.Drawing.Bitmap(valFichierChoisi.InputStream))
                {
                }
            }
            catch (Exception)
            {
                return new ValidationResult(ErrorMessage);
            }


        }
        return ValidationResult.Success;

    }

}

我是为服务器端做的。对于客户端验证,使用jquery unobstrusive验证更加困难只有一个原因:它可以返回一个值。让我解释。假设这个验证结果。

   $.validator.unobtrusive.adapters.add('fichimage', ['thefile'],
function (options) {
    options.rules['fichimage'] = options.params;
    if (options.message) {
        options.messages['fichimage'] = options.message;
    }
   }
 );

$.validator.addMethod('fichimage', function (value, element, params) {
    var lechoifait = $('input[name="' + params.thefile+ '"]').val();

    if (value != null && value == lechoifait) {
  //suppose that your browser allow the use of filereader
  //know that you can obtain the selected file by using element.files[0]
  var fr = new FileReader();
  fr.onloadend = function (e) {
   //Because this is done asynchronously
   // the return will always be true for this validation no matter the kind of file 

 //apart of this, if you want to use any callback function,  you will use it in this function which don't allows any return 
   };
fr.readAsDataURL(element.files[0]);

        }
     //this will always be true because of the asynchronously behaviour of onloadend function
        return true;

}, '');

这就是为什么我建议您实施自己的方法来解决这个问题  根据@Drakes(How to check file MIME type with javascript before upload?)给出的答案,我提出了这个答案。

假设在成功的情况下,您想要在此图像中加载图像

  <img  id="imagetoshow" alt="" src=""  style=" width :80%; height :300px; display:none; "/>

因为你正在使用mvc,你的html助手可能是那样的

     @Html.TextBoxFor(m => m.selectedimage, new { type = "file", @class = "someclass", onchange = "checkandshow(this)" })
     //this validation message is for checking for server side
     //try another way if you are not using a model as claimed
     @Html.ValidationMessageFor(m => m.selectedimage)
     //you could use this label in the case of incorrect file
      @Html.Label("", new { id = "badfile", @class = "badimageselected"})

如果您选择图像(我只检查jpeg),将执行checkandshow(this)功能。对于其他类型文件的签名,请参阅此(https://en.wikipedia.org/wiki/List_of_file_signatures)和/或此(https://mimesniff.spec.whatwg.org/#matching-an-image-type-pattern

 function checkandshow(input) {
//imagetoshow is the id of the image tag where you want to load your image in the case of success
   $('#imagetoshow').attr('src', '');
  //you first check if the element contains any file
if (input.files && input.files[0]) {
   // you check if the browser support filereader
    if (window.FileReader && window.Blob) {
  //because the browser support this, you create an object of this class
        var filerdr = new FileReader();
        filerdr.onload = function (e) {
   //this subarray will allows you to check the first 4 bytes of the image
            var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
            var header = "";
            for (var i = 0; i < arr.length; i++) {
                header += arr[i].toString(16);
            } 
    //typeFichier function will allows you obtaining the real mime of the file
            var letype = typeFichier(header);
            if (letype != 'image/jpeg') {
   //in the case that it is not you type of file, just do whatever you want
  //set the text in the label to prevent the user of this bad file 
   $("#badfile").text('The selected file is not a jpeg or jpg file.');
            }
            else {
   //in the case of the good real MIME, you remove the text in the label and then load your image to the corresponding place
                $("#badfile").text('');
                //you just load the correct image
                var loaderfr = new FileReader();
                loaderfr.onload = function (c) {
      //because the image is just show when you select the file, you change display: none and allow it be seen
                   $("#imagetoshow").show()
                    $('#imagetoshow').attr('src', c.target.result);
                }
      //this is for loading the image
                loaderfr.readAsDataURL(input.files[0]);
            }
        }
    //this is for loading the array buffer which will allows the bytes of the file to be checked
        filerdr.readAsArrayBuffer(input.files[0]);

    } else {
        //in the case that File and Blob are not supported
          $("#imagetoshow").show()
       //you change the height because you want to reduce the space
       $('#imagetoshow').height(15);
        $('#imagetoshow').attr('alt', 'Sorry, your browser do not allows a preview of the selected image, migrate to another version of the browser or to other browser which allows this preview.');
    }


  }
 };

标签的nonimage类可能是这样的

 .nonimage { color: Red;font-weight:bold ; font-size:24px; }

这是允许获取文件的真实MIME的函数

  function typeFichier(entete) {
        switch (entete) {
            case "ffd8ffe0":
            case "ffd8ffe1":
            case "ffd8ffe2":
                type = "image/jpeg";
                break;
            default:
                type = "unknown";
                break;
        }
        return type;
    };

如果要使用模型,请不要忘记添加必需的属性,以便检查服务器端的文件,如下所示

  [Required(FileType="selectedimage", ErrorMessage = "It seems that your file is incorrect, please try another one.")]
  public HttpPostedFileBase selectedimage{ get; set; }

我强烈建议您使用模型进行此类验证