Validação da extensão do arquivo antes de enviar o arquivo

92

Estou enviando imagens para um servlet. A validação se o arquivo carregado é uma imagem é feita apenas no lado do servidor, verificando os números mágicos no cabeçalho do arquivo. Existe alguma maneira de validar as extensões no lado do cliente antes de enviar o formulário ao servlet? Assim que pressiono enter, o upload é iniciado.

Estou usando Javascript e jQuery no lado do cliente.

Atualização: Eu finalmente terminei com a validação do lado do servidor que lê bytes e rejeita o upload se não for uma imagem.


fonte
2
Você está usando o Uploadify conforme sugerido em uma de suas perguntas anteriores, certo?
BalusC de
Não, ele para entre 50-96. Tentei várias vezes com várias entradas. E eu também estava com pressa por uma solução na época. Então, eu tentei simples jquery.ProgressBar.js. Funciona bem. ### Então, posso validar com uploadify !!!
Não podemos simplesmente usar o atributo accept na tag de entrada para ter certeza de que o usuário seleciona o arquivo do formato especificado?
AnonSar

Respostas:

118

É possível verificar apenas a extensão do arquivo, mas o usuário pode facilmente renomear virus.exe para virus.jpg e "passar" na validação.

Pelo que vale a pena, aqui está o código para verificar a extensão do arquivo e abortar se não atender a uma das extensões válidas: (escolha o arquivo inválido e tente enviar para ver o alerta em ação)

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>

Observe que o código permitirá que o usuário envie sem escolher o arquivo ... se for necessário, remova a linha if (sFileName.length > 0) {e seu colchete de fechamento associado. O código validará qualquer entrada de arquivo no formulário, independentemente de seu nome.

Isso pode ser feito com jQuery em menos linhas, mas estou confortável o suficiente com JavaScript "bruto" e o resultado final é o mesmo.

Caso você tenha mais arquivos ou queira acionar a verificação ao alterar o arquivo e não apenas no envio do formulário, use esse código:

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

Isso mostrará um alerta e redefinirá a entrada em caso de extensão de arquivo inválida.

Shadow Wizard está vacinando
fonte
Eu gostaria apenas de acrescentar que usar "onSubmit" em vez de "onChange" é complicado - especialmente se a opção "múltiplo" for usada. Cada arquivo deve ser verificado conforme selecionado, não quando todo o formulário é postado.
DevlshOne
@DevlshOne ideia interessante, mencionarei isso também no post. Obrigado!
Shadow Wizard está vacinando em
Muito obrigado por este código do @Shadow Wizard. Realmente me ajudou muito!
Anahit Ghazaryan
1
@garryman falha como? A questão aqui não menciona que o arquivo é obrigatório. Se no seu caso o arquivo é um campo obrigatório, você pode mover a linha var blnValid = false;para ficar acima do loop sobre arrInputs, então após o loop verificar a variável blnValid: se verdadeiro, deixe o formulário enviar, caso contrário, mostre o alerta de que o arquivo é necessário.
Shadow Wizard está vacinando
verifique minha resposta abaixo
Divyesh Jani
75

Nenhuma das respostas existentes parecia compacta o suficiente para a simplicidade do pedido. Verificar se um determinado campo de entrada de arquivo tem uma extensão de um conjunto pode ser feito da seguinte forma:

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

Portanto, o uso de exemplo pode ser (onde uploadé o idde uma entrada de arquivo):

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

Ou como um plugin jQuery:

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

Exemplo de uso:

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

O .replace(/\./g, '\\.')existe para escapar do ponto para a expressão regular, de modo que as extensões básicas possam ser passadas sem os pontos correspondendo a qualquer caractere.

Não há verificação de erros para mantê-los curtos, presumivelmente, se você usá-los, terá certeza de que a entrada existe primeiro e que o array de extensões é válido!

Orbling
fonte
10
Agradável. Observe que esses scripts diferenciam maiúsculas de minúsculas. Para resolver isso, você precisa darRexExp the "i" modifier, for example: return (new RegExp('(' + exts.join('|').replace(/\./g, '\\.') + ')$', "i")).test(fileName);
Tedd Hansen
2
Um pouco difícil de ler, mas isso significa adicionar , "i"após o final da string regex ( )$'). Isso adicionará suporte para qualquer capitalização na extensão de nome de arquivo (.jpg, .JPG, .Jpg, etc ...)
Tedd Hansen
Obrigado, Tedd, seria melhor ter uma correspondência que não diferencia maiúsculas de 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
fonte
1
Obrigado, muito simples e limpo.
Th3_hide
se você pressionar cancelar, um alerta será disparado.
PinoyStackOverflower
18

Vim aqui porque tinha certeza de que nenhuma das respostas aqui era muito ... 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
fonte
Obrigado, isso funciona no Angular com poucas modificações, obrigado
skydev
funcionou bem para mim, embora seja necessário cortar quaisquer espaços à direita do nome antes de testar. +1
Roberto
9

verifique se o arquivo está selecionado ou não

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

verifique a extensão do arquivo

  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
fonte
8

Eu gosto deste exemplo:

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

Você usa o tipo de entrada = "arquivo" para escolher os arquivos de upload? em caso afirmativo, por que não usar o atributo accept?

<input type="file" name="myImage" accept="image/x-png,image/gif,image/jpeg" />
Rouven
fonte
Este! accept="image/*"é definitivamente a escolha mais inteligente na maioria dos casos.
Alberto T.
6

Se você precisar testar urls remotos em um campo de entrada, pode tentar testar um regex simples com os tipos de seu interesse.

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

Isso irá capturar qualquer coisa que termine em .gif, .jpg, .jpeg, .tiff ou .png

Devo observar que alguns sites populares como o Twitter acrescentam um atributo de tamanho ao final de suas imagens. Por exemplo, o seguinte falhará neste teste, embora seja um tipo de imagem válido:

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

Por isso, esta não é uma solução perfeita. Mas isso o levará a cerca de 90% do caminho.

user3789031
fonte
4

tente isso (funciona para mim)

  
  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
fonte
2

Outro exemplo hoje em dia via 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
fonte
1

Aqui está uma maneira mais reutilizável, supondo que você use jQuery

Função de biblioteca (não requer 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) }

Função de página (requer 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.
fonte
1

[TypeScript]

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
fonte
1

Você pode usar o acceptatributo disponível para tipos de arquivo de entrada. Verificar documentação MDN

Aditibtp
fonte
2
Com isso, você ainda pode selecionar outros tipos de arquivo
César León
@ CésarLeón Sim. O usuário tem a opção de selecionar todos os arquivos. Se você quiser restringir isso também, precisará fazer a validação manual. Verifique outras respostas.
Madura Pradeep de
1

É assim que é feito no jquery

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

Quando você quiser validar o botão de navegação e a extensão do arquivo, use 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
fonte
1
quando você quiser validar o botão de navegação e a extensão do arquivo, use este código.
Ajay Kumar Gupta,
1

Acho melhor tentar com o tipo MIME do que verificar a extensão. Porque, às vezes, arquivos podem existir sem ele e eles estão funcionando muito bem em sistemas Linux e Unix.

Então, você pode tentar algo assim:

["image/jpeg", "image/png", "image/gif"].indexOf(file.type) > -1
Dananjaya
fonte
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
fonte
3
Seria melhor se você escrevesse uma breve descrição de sua resposta.
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
fonte
0

Você pode criar uma matriz que inclui o tipo de arquivo necessário e usar $ .inArray () em jQuery para verificar se o tipo de arquivo existe na 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
fonte
0

podemos verificá-lo no envio ou podemos fazer um evento de mudança desse controle

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
fonte
-1

Esta é a melhor solução na minha opinião, que é muito mais curta do que as outras:

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

Neste caso, a função é chamada a partir de um controle Kendo Upload com esta configuração:

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

Andrew
fonte