web-dev-qa-db-fra.com

Télécharger des fichiers à l'aide du champ input type = "file" avec l'événement .change () qui ne se déclenche pas toujours IE et Chrome

J'ai un simple morceau de code pour télécharger des fichiers:

$(document).ready(function () {
    $(".attachmentsUpload input.file").change(function () {
        $('form').submit();
    });
});

<form class="attachmentsUpload" action="/UploadHandler.ashx" method="post" enctype="multipart/form-data">
    <input type="file" class="file" name="file" />
</form>

Pendant que je clique sur l'entrée, puis que je sélectionne un fichier dans la boîte de dialogue, je soumets ce fichier en utilisant ajax. Ce n'est pas une partie importante ici. Il est important de noter que même si je sélectionne le même fichier une deuxième fois dans la boîte de dialogue, juste après la soumission du premier fichier, l'événement .change () ne se déclenche pas dans IE et Chrome. Mais pendant que je choisis un fichier différent, l'événement est déclenché et fonctionne correctement. Sous Firefox, il se déclenche tout le temps.

Comment contourner ce problème, fonctionner comme prévu (comme dans Firefox)?

22
jwaliszko

La description

Cela est dû au fait que la valeur du champ de saisie (le chemin de fichier sélectionné) ne change pas si vous sélectionnez à nouveau le même fichier.

Vous pouvez définir la valeur de l'événement onChange() sur une chaîne vide et soumettre votre formulaire uniquement si la valeur n'est pas vide. Jetez un oeil à mon échantillon et à cette jsFiddle Demonstration .

Échantillon

$(".attachmentsUpload input.file").change(function () {
    if ($(".attachmentsUpload input.file").val() == "") {
        return;
    }
    // your ajax submit
    $(".attachmentsUpload input.file").val("");
});

Mettre à jour

Ceci, pour une raison quelconque, ne fonctionne pas dans IE9. Vous pouvez remplacer l'élément pour les réinitialiser. Dans ce cas, vous avez besoin de jQuery live() pour lier l'événement, car votre champ de saisie sera (re) créé (e) dynamiquement. Cela fonctionnera dans tous les navigateurs.

J'ai trouvé cette solution sur la réponse de stackoverflow Effacement du type d'entrée = 'fichier' à l'aide de jQuery

$(".attachmentsUpload input.file").live("change", function () {
    if ($(".attachmentsUpload input.file").val() == "") {
        return;
    }
    // get the inputs value
    var fileInputContent = $(".attachmentsUpload input.file").val();
    // your ajax submit
    alert("submit value of the file input field=" + fileInputContent);
    // reset the field
    $(".attachmentsUpload input.file").replaceWith('<input type="file" class="file" name="file" />');
});​

Plus d'information

Découvrez mes mises à jour jsFiddle

Remarque:live est maintenant supprimé des versions ultérieures de jQuery. Veuillez utiliser on au lieu de live.

29
dknaack

Sur la base de la réponse de dknaack, l'indice est l'utilisation de jquery live pour lier l'événement de modification et la réinitialisation du champ d'entrée après l'envoi :

$(document).ready(function () {
    $(".attachmentsUpload input.file").change(function () {
        $('form').submit();  /* sync submit */
        $(".attachmentsUpload input.file").replaceWith('<input type="file" class="file" name="file" />');
    });
});

La réinitialisation doit être effectuée après que submit event est terminé. Lorsque submit est async , réinitialisez le champ par exemple dans ajax success event.

$(document).ready(function () {
    $(".attachmentsUpload input.file").change(function () {
        $('form').submit();  /* async submit */
    });
});

.ajaxForm({
    ...
    success: function (result) {
        // reset the field - needed for IE to upload the same file second time                    
        $this.find("input.file").replaceWith('<input type="file" class="file" name="file" />');
    }
});
1
jwaliszko