L'événement de sélection du fichier d'entrée HTML ne se déclenche pas lors de la sélection du même fichier

204

Y a-t-il une chance de détecter chaque sélection de fichier effectuée par l'utilisateur pour un élément HTML inputde type file?

Cela a été demandé plusieurs fois auparavant, mais l' onchangeévénement généralement proposé ne se déclenche pas si l'utilisateur sélectionne à nouveau le même fichier.

dronus
la source
7
Votre code devrait-il alors également se déclencher si l'utilisateur clique ensuite sur Annuler? On s'attend à ce qu'appuyer sur Annuler ne fasse rien, et je pense que la plupart des utilisateurs s'attendraient en outre à ce que la resélection du même fichier ait le même effet qu'Annuler. Je ne sais pas si cela est possible ou non, mais je vous suggère de reconsidérer cette conception de toute façon.
KRyan
1
En cas d'annulation, il ne devrait pas se déclencher ou le rendre autrement détectable. Il est plus destiné à supprimer un ceveat de l'interface utilisateur: si une action est invoquée après la sélection du fichier, l'utilisateur s'attend généralement à ce que l'action se répète s'il choisit à nouveau le fichier.
dronus
Nous pouvons peut-être avoir ce comportement si nous définissons la inputvaleur s sur '' après avoir fait quelque chose avec le fichier. Mais cela supprimerait également le nom de fichier visible. Cependant, cela peut être correct, car le fichier est réellement traité et le résultat de cette action peut apparaître ailleurs.
dronus
Plz Expliquez le Que Que voulez-vous faire?
Champ
1
Tout ce que je veux, c'est simuler le comportement des anciennes applications bureautiques. Si j'ouvre à nouveau le même fichier dans une application de bureau, il est généralement rechargé, ou si une action est effectuée avec le fichier (comme le convertir en un autre format par exemple), cette action est à nouveau effectuée. C'est ce que les utilisateurs de bureau peuvent également attendre d'une application Web, mais l' événement d' fileentrée onchangene ressemble pas.
dronus

Réponses:

279

Définissez la valeur de inputto nullsur chaque onclickévénement. Cela réinitialisera la inputvaleur de et déclenchera l' onchangeévénement même si le même chemin est sélectionné.

input.onclick = function () {
    this.value = null;
};

input.onchange = function () {
    alert(this.value);
};​

Voici une DÉMO .

Remarque: C'est normal si votre fichier est préfixé par 'C: \ fakepath \'. C'est une fonction de sécurité qui empêche JavaScript de connaître le chemin absolu du fichier. Le navigateur le sait toujours en interne.

Brian Ustas
la source
1
J'ai essayé la démo, mais (en utilisant Chrome 21), je reçois toujours `C: \ fakepath` + puis le nom de fichier que j'ai sélectionné (à l'exclusion du chemin). L'alerte est cependant affichée sur chaque sélection du même fichier.
Jasper de Vries
1
@JasperdeVries C'est une fonction de sécurité qui empêche JavaScript de connaître le chemin absolu d'un fichier. Le navigateur connaît toujours le chemin en interne.
Brian Ustas
1
En aparté, null est la seule valeur autorisée pour <input type = "file">. Donc, si vous essayez de le définir sur undefined et d'obtenir une exception, c'est la raison.
Noel Abrahams
5
Cela ne fonctionne pas bien dans IE11, sauf si vous apportez une petite modification: démo .
21
Il vaut mieux le mettre this.value = nullà la fin du onchangecar il est possible d'activer un élément d'entrée sans cliquer dessus (en utilisant le clavier). Vous pouvez stocker input.filessi vous avez besoin de le référencer plus tard.
Halcyon
24
<form enctype='multipart/form-data'>
    <input onchange="alert(this.value); this.value=null; return false;" type='file'>
    <br>
    <input type='submit' value='Upload'>
</form>

this.value=null; n'est nécessaire que pour Chrome, Firefox fonctionnera bien uniquement avec return false;

Voici un FIDDLE

elshnkhll
la source
2
simple et efficace vient d'être testé dans les derniers IE et chrome et fonctionne comme un charme. Merci de le partager
Atul Chaudhary
8

Dans cet article, sous le titre "Utilisation de la saisie de formulaire pour la sélection"

http://www.html5rocks.com/en/tutorials/file/dndfiles/

<input type="file" id="files" name="files[]" multiple />

<script>
function handleFileSelect(evt) {

    var files = evt.target.files; // FileList object

    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
     // Code to execute for every file selected
    }
    // Code to execute after that

}

document.getElementById('files').addEventListener('change', 
                                                  handleFileSelect, 
                                                  false);
</script>

Il ajoute un écouteur d'événements pour «changer», mais je l'ai testé et il se déclenche même si vous choisissez le même fichier et non si vous annulez.

Xacur Aphrantus
la source
Compte tenu de la signification potentiellement ambiguë de «changement» dans ce cas, avez-vous essayé cela dans plusieurs navigateurs? Vous voudrez peut-être spécifier ceux sur lesquels vous l'avez essayé, car sur le Web, les navigateurs ne sont pas exactement toujours d'accord sur ces choses.
Thor84no
2
Quel environnement utilisez-vous pour votre test? Mon expérience avec Chrome était celle que j'ai indiquée dans la question, l' changeévénement ne se déclencherait que sur les changements de nom de fichier.
dronus
7

Utilisez l'événement onClick pour effacer la valeur de l'entrée cible, chaque fois que l'utilisateur clique sur le champ. Cela garantit que l'événement onChange sera également déclenché pour le même fichier. A travaillé pour moi :)

onInputClick = (event) => {
    event.target.value = ''
}

<input type="file" onChange={onFileChanged} onClick={onInputClick} />

Utilisation de TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}
Trafalgar Law
la source
Merci pour la solution.
Deepak Tekchandani
1

Faites ce que vous voulez faire après le chargement réussi du fichier. Juste après la fin de votre traitement de fichier, définissez la valeur du contrôle de fichier sur une chaîne vide. Ainsi, le .change () sera toujours appelé même si le nom du fichier change ou non. comme par exemple, vous pouvez faire cette chose et travailler pour moi comme un charme

   $('#myFile').change(function () {
       LoadFile("myFile");//function to do processing of file.
       $('#myFile').val('');// set the value to empty of myfile control.
    });
Mohit Singh
la source
1
handleChange({target}) {
    const files = target.files
    target.value = ''
}
Shashwat Gupta
la source
1
Hé ngCourse! Les réponses uniquement codées peuvent résoudre le problème, mais elles sont beaucoup plus utiles si vous expliquez comment elles le résolvent. La communauté a besoin de la théorie ainsi que du code pour comprendre pleinement votre réponse.
RBT
Bien que ce code puisse résoudre la question, y compris une explication de comment et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre message, et entraînerait probablement plus de votes positifs. N'oubliez pas que vous répondrez à la question des lecteurs à l'avenir, pas seulement à la personne qui pose la question maintenant. Veuillez modifier votre réponse pour ajouter des explications et donner une indication des limitations et hypothèses applicables. De l'avis
double-bip
1

Effacer la valeur du 0ème indice d'entrée a fonctionné pour moi . Veuillez essayer le code ci-dessous, j'espère que cela fonctionnera (AngularJs).

          scope.onClick = function() {
            input[0].value = "";
                input.click();
            };
Dilip Kumar
la source