Validación de la extensión del archivo antes de cargar el archivo

90

Estoy subiendo imágenes a un servlet. La validación de si el archivo cargado es una imagen se realiza solo en el lado del servidor, al verificar los números mágicos en el encabezado del archivo. ¿Hay alguna forma de validar las extensiones en el lado del cliente antes de enviar el formulario al servlet? Tan pronto como presiono Enter, comienza a cargarse.

Estoy usando Javascript y jQuery en el lado del cliente.

Actualización: finalmente terminé con la validación del lado del servidor que lee bytes y rechaza la carga si no es una imagen.


fuente
2
Estás usando Uploadify como se sugiere en una de tus preguntas anteriores, ¿verdad?
BalusC
No, se detiene entre 50 y 96. Intenté muchas veces con varias entradas. Y en ese momento también tenía prisa por encontrar una solución. Entonces, le di una oportunidad a simple jquery.ProgressBar.js. Funciona bien. ### Entonces, ¿puedo validar con uploadify?
¿No podemos simplemente usar el atributo de aceptación en la etiqueta de entrada para asegurarnos de que el usuario selecciona el archivo del formato especificado?
AnonSar

Respuestas:

117

Es posible verificar solo la extensión del archivo, pero el usuario puede cambiar fácilmente el nombre de virus.exe a virus.jpg y "pasar" la validación.

Por lo que vale, aquí está el código para verificar la extensión del archivo y cancelar si no cumple con una de las extensiones válidas: (elija un archivo no válido e intente enviarlo para ver la alerta en acción)

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>

Tenga en cuenta que el código permitirá al usuario enviar sin elegir el archivo ... si es necesario, elimine la línea if (sFileName.length > 0) {y su corchete de cierre asociado. El código validará cualquier entrada de archivo en el formulario, independientemente de su nombre.

Esto se puede hacer con jQuery en menos líneas, pero me siento bastante cómodo con JavaScript "crudo" y el resultado final es el mismo.

En caso de que tenga más archivos, o desee activar la verificación al cambiar el archivo y no solo en el envío del formulario, use dicho código en su lugar:

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 />

Esto mostrará una alerta y restablecerá la entrada en caso de una extensión de archivo no válida.

Shadow Wizard es el oído para ti
fuente
Solo me gustaría agregar que usar "onSubmit" en lugar de "onChange" es engorroso, especialmente si se usa la opción "multiple". Cada archivo debe revisarse como se seleccionó, no cuando se publica el formulario completo.
DevlshOne
@Devlsh: Una idea interesante, mencionaré esto también en la publicación. ¡Gracias!
Shadow Wizard es Ear For You
Muchas gracias por este código @Shadow Wizard ¡Realmente me ayudó mucho!
Anahit Ghazaryan
1
@garryman falla, ¿cómo? La pregunta aquí no menciona que el archivo es obligatorio. Si en su caso, el archivo es un campo obligatorio, puede mover la línea var blnValid = false;para que esté por encima del bucle sobre arrInputs, luego, después del bucle, verifique la variable blnValid: si es verdadera, deje que el formulario se envíe, de lo contrario, muestre la alerta de que el archivo es obligatorio.
Shadow Wizard es tu oreja
verifique mi respuesta a continuación
Divyesh Jani
73

Ninguna de las respuestas existentes parecía lo suficientemente compacta para la simplicidad de la solicitud. La verificación de si un campo de entrada de archivo dado tiene una extensión de un conjunto se puede lograr de la siguiente manera:

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

Entonces, el uso de ejemplo podría ser (donde uploadestá la identrada de un archivo):

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

O como un complemento de jQuery:

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

Uso de ejemplo:

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

El .replace(/\./g, '\\.')está allí para escapar del punto para la expresión regular de modo que las extensiones básicas se pueden pasar sin los puntos en juego cualquier carácter.

No hay ningún error al verificar estos para mantenerlos cortos, presumiblemente si los usa, se asegurará de que la entrada exista primero y que la matriz de extensiones sea válida.

Orbling
fuente
10
Agradable. Tenga en cuenta que estos scripts distinguen entre mayúsculas y minúsculas. Para resolver esto necesitas darRexExp the "i" modifier, for example: return (new RegExp('(' + exts.join('|').replace(/\./g, '\\.') + ')$', "i")).test(fileName);
Tedd Hansen
2
Un poco difícil de leer, pero eso significa agregar , "i"después del final de la cadena de expresiones regulares ( )$'). Esto agregará soporte para cualquier carcasa en la extensión de nombre de archivo (.jpg, .JPG, .Jpg, etc.)
Tedd Hansen
Gracias, Tedd, sería mejor tener coincidencias sin distinción entre mayúsculas y minúsculas.
Orbling
39
$(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');
        }
    });
});
Ashish pathak
fuente
1
Gracias, muy sencillo y limpio.
Th3_hide
si presiona cancelar, activará una alerta.
PinoyStackOverflower
18

Vine aquí porque estaba seguro de que ninguna de las respuestas aquí era bastante ... poética:

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()"/>

Cedric Ipkiss
fuente
Gracias, esto funciona en Angular con pocas modificaciones, gracias
skydev
funcionó bien para mí, aunque uno debería recortar los espacios finales del nombre antes de probar. +1
Roberto
9

comprobar que si el archivo está seleccionado o no

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

comprobar la extensión del archivo

  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;
             }
    }
Rizwan Gill
fuente
8

Me gusta este ejemplo:

<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>
kamal.shalabe
fuente
7

¿Utiliza el tipo de entrada = "archivo" para elegir los archivos de carga? Si es así, ¿por qué no utilizar el atributo accept?

<input type="file" name="myImage" accept="image/x-png,image/gif,image/jpeg" />
Rouven
fuente
¡Esta! accept="image/*"definitivamente es la opción más inteligente en la mayoría de los casos.
Alberto T.
6

Si necesita probar direcciones URL remotas en un campo de entrada, puede probar una expresión regular simple con los tipos que le interesan.

$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;
}

Esto capturará cualquier cosa que termine en .gif, .jpg, .jpeg, .tiff o .png

Debo señalar que algunos sitios populares como Twitter agregan un atributo de tamaño al final de sus imágenes. Por ejemplo, lo siguiente fallaría en esta prueba aunque sea un tipo de imagen válido:

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

Por eso, esta no es una solución perfecta. Pero te llevará aproximadamente al 90% del camino.

usuario3789031
fuente
4

prueba esto (funciona para mí)

  
  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>

     

AlphaOne
fuente
2

Otro ejemplo actual a través de 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'));

Penny Liu
fuente
1

Aquí hay una forma más reutilizable, suponiendo que use jQuery

Función de biblioteca (no requiere 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) }

Función de página (requiere jQuery (apenas)):

$("[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;
});
Micah B.
fuente
1

[Mecanografiado]

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;
});
mkupiniak
fuente
1

Puede utilizar el acceptatributo disponible para los tipos de archivos de entrada. Verifique la documentación de MDN

Aditibtp
fuente
2
Con esto aún puede seleccionar otros tipos de archivos
César León
@ CésarLeón Sí. El usuario tiene la opción de seleccionar todos los archivos. Si desea restringir eso también, debe realizar una validación manual. Verifique otras respuestas.
Madura Pradeep
1

Así es como se hace en jquery

$("#artifact_form").submit(function(){
    return ["jpg", "jpeg", "bmp", "gif", "png"].includes(/[^.]+$/.exec($("#artifact_file_name").val())[0])
  });
Abhiyan Timilsina
fuente
1

Cuando desee validar el botón de exploración y la extensión del archivo, utilice este código:

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;
}
Ajay Kumar Gupta
fuente
1
cuando desee validar el botón de exploración y la extensión del archivo, utilice este código.
Ajay Kumar Gupta
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>
user3060112
fuente
3
Sería mejor si escribiera una breve descripción de su respuesta.
Roopendra
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 />

francin
fuente
0

Puede crear una matriz que incluya el tipo de archivo que se necesita y usar $ .inArray () en jQuery para verificar si existe el tipo de archivo en la matriz.

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');
}
John Roca
fuente
0

podemos verificarlo al enviarlo o podemos hacer un evento de cambio de ese 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;
    }
Divyesh Jani
fuente
0

Creo que es mejor intentarlo con mimetype que comprobar la extensión. Porque, a veces, los archivos pueden existir sin él y funcionan muy bien en sistemas Linux y Unix.

Entonces, puedes probar algo como esto:

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

Esta es la mejor solución en mi opinión, que es mucho más corta que las otras:

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();
    }
}

En este caso, la función se llama desde un control de carga de Kendo con esta configuración:

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

Andrés
fuente