Comment détecter le type d'entrée = fichier «changement» pour le même fichier?


131

Je souhaite déclencher un événement lorsque l'utilisateur sélectionne un fichier. Le faire avec.change événement si l'utilisateur modifie le fichier à chaque fois.

Mais je veux déclencher l'événement si l'utilisateur sélectionne à nouveau le même fichier.

  1. Fichier de sélection de l'utilisateur A.jpg(l'événement se déclenche)
  2. Fichier de sélection de l'utilisateur B.jpg(l'événement se déclenche)
  3. Fichier de sélection de l'utilisateur B.jpg(l'événement ne se déclenche pas, je veux qu'il se déclenche)

Comment puis-je le faire?

Réponses:


78

Vous pouvez le tromper. Supprimez l'élément de fichier et ajoutez-le au même endroit lors de l' changeévénement. Cela effacera le chemin du fichier, ce qui le rendra modifiable à chaque fois.

Exemple sur jsFiddle.

Ou vous pouvez simplement utiliser .prop("value", ""), voir cet exemple sur jsFiddle .

  • jQuery 1.6+ prop
  • Versions précédentes attr

@Pekka: Pas exactement. Mais il peut simplement l'adapter. Disons qu'il doit publier le fichier. Après la publication, il peut appeler une fonction js qui supprimera et ajoutera le nouveau sélecteur de fichier. C'est faisable.
BrunoLM

3
sachez que lorsque vous utilisez .attr("value", "")ou .val("")(comme suggéré par @ wagner-leonardi ci-dessous), Internet Explorer déclenchera l'événement de changement alors que Chrome ne le fera pas
fadomire

4
puisque "value" est une propriété et non un attribut d'entrée, l'utilisation recommandée de jQuery serait.prop("value", "")
Roger Barreto

70

Si vous avez essayé .attr("value", "")et que vous n'avez pas travaillé, ne paniquez pas (comme je l'ai fait)

faites simplement à la .val("")place et fonctionnera bien


49

Vous pouvez simplement définir à null le chemin du fichier chaque fois que l'utilisateur clique sur le contrôle. Désormais, même si l'utilisateur sélectionne le même fichier, l' événement onchange sera déclenché.

<input id="file" onchange="file_changed(this)" onclick="this.value=null;" type="file" accept="*/*" />

2
J'avais besoin d'une solution comme celle-ci. Il est vraiment court et fait le travail. Belle pensée Mariusz Wiazowski.
Jay Dharmendra Solanki

Une autre solution consiste à modifier la valeur lorsque la balise d'entrée est modifiée. Mais nous ne nous attendons pas à ce que la valeur soit modifiée après avoir sélectionné un fichier.
songgeb

1
Cool, bien mieux que de supprimer et d'ajouter à nouveau l'élément dans le dom, merci
David Dal Busco

24

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 = ''
}

17

J'ai fait fonctionner cela en effaçant la valeur d'entrée du fichier onClick, puis en publiant le fichier onChange. Cela permet à l'utilisateur de sélectionner le même fichier deux fois de suite tout en conservant le déclenchement de l'événement de modification à publier sur le serveur. Mon exemple utilise le plugin de formulaire jQuery .

$('input[type=file]').click(function(){
    $(this).attr("value", "");
})  
$('input[type=file]').change(function(){
    $('#my-form').ajaxSubmit(options);      
})

onClickse déclenche avant onChange, donc cette méthode fonctionne très bien pour moi.
iplus26

8

Ce travail pour moi

<input type="file" onchange="function();this.value=null;return false;">

1
je suppose que vous vouliez dire quelque chose comme function () {this.value = null; retourner faux; }
Jacek Pietal

7

Solution VueJs

<input
                type="file"
                style="display: none;"
                ref="fileInput"
                accept="*"
                @change="onFilePicked"
                @click="$refs.fileInput.value=null"
>

1
Merci pour cette réponse de variation
Coisox

5

Inspiré de @braitsch, j'ai utilisé ce qui suit dans mon AngularJS2 input-file-component

<input id="file" onclick="onClick($event) onchange="onChange($event)" type="file" accept="*/*" />

export class InputFile {

    @Input()
    file:File|Blob;

    @Output()
    fileChange = new EventEmitter();

    onClick(event) {
        event.target.value=''
    }
    onChange(e){
        let files  = e.target.files;
        if(files.length){
            this.file = files[0];
        }
        else { this.file = null}
        this.fileChange.emit(this.file);
    }
}

Voici le onClick(event)m'a sauvé :-)


3

La chose la plus simple à faire est probablement de définir la valeur sur une chaîne vide. Cela l'oblige à «changer» le fichier à chaque fois, même si le même fichier est à nouveau sélectionné.

<input type="file" value="" />


3

Voici la solution React-y Way que j'ai trouvée qui a fonctionné pour moi:

onClick={event => event.target.value = null}


2

Si vous ne souhaitez pas utiliser jQuery

<form enctype='multipart/form-data'>
    <input onchange="alert(this.value); return false;" type='file'>
    <br>
    <input type='submit' value='Upload'>
</form>

Cela fonctionne bien dans Firefox, mais pour Chrome, vous devez ajouter this.value=null;après l'alerte.


2

Par défaut, la propriété value de l'élément d'entrée est effacée après la sélection des fichiers si l'entrée a plusieurs attributs. Si vous ne nettoyez pas cette propriété, l'événement "modification" ne sera pas déclenché si vous sélectionnez le même fichier. Vous pouvez gérer ce comportement à l'aide de l' multipleattribut.

<!-- will be cleared -->
<input type="file" onchange="yourFunction()" multiple/>
<!-- won't be cleared -->
<input type="file" onchange="yourFunction()"/>

Référence


1

Vous ne pouvez pas faire de changefeu ici (comportement correct, puisque rien n'a changé). Cependant, vous pouvez également vous lier click... bien que cela puisse tirer trop souvent ... il n'y a pas beaucoup de terrain d'entente entre les deux cependant.

$("#fileID").bind("click change", function() {
  //do stuff
});

Il semble que vous ne faites que répéter ses paroles et que ce .click()n'est pas "feu sur re-select".
BrunoLM

@BrunoLM - Non, ce n'est pas ... mais je pense que vous avez lu la partie où je dis que vous ne pouvez pas faire cela, clickc'est aussi proche que possible.
Nick Craver

1

Créez pour l'entrée un événement de clic et un événement de modification. L'événement click vide l'entrée et l'événement change contient le code que vous souhaitez exécuter.

Ainsi, l'événement de clic se vide lorsque vous cliquez sur le bouton d'entrée (avant que la fenêtre de sélection de fichier ne s'ouvre), par conséquent, l'événement de modification se déclenchera toujours lorsque vous sélectionnez un fichier.

$("#input").click(function() {
  $("#input").val("")
});

$("#input").change(function() {
  //Your code you want to execute!
});
<input id="input" type="file">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>


0

Vous pouvez utiliser form.reset()pour effacer la filesliste des entrées de fichier . Cela réinitialisera tous les champs aux valeurs par défaut, mais dans de nombreux cas, vous n'utiliserez peut-être que l'entrée type = 'file' dans un formulaire pour télécharger des fichiers de toute façon. Dans cette solution, il n'est pas nécessaire de cloner l'élément et de reconnecter les événements.

Merci à philiplehmann


0

Je suis tombé sur le même problème, j'ai parcouru les solutions ci-dessus mais ils n'ont pas obtenu de bonne explication de ce qui se passait vraiment.

Cette solution que j'ai écrite https://jsfiddle.net/r2wjp6u8/ ne fait pas beaucoup de changements dans l'arborescence DOM, elle change juste les valeurs du champ de saisie. Du point de vue des performances, cela devrait être un peu mieux.

Lien vers violon: https://jsfiddle.net/r2wjp6u8/

<button id="btnSelectFile">Upload</button>

<!-- Not displaying the Inputfield because the design changes on each browser -->
<input type="file" id="fileInput" style="display: none;">
<p>
  Current File: <span id="currentFile"></span>
</p>
<hr>
<div class="log"></div>


<script>
// Get Logging Element
var log = document.querySelector('.log');

// Load the file input element.
var inputElement = document.getElementById('fileInput');
inputElement.addEventListener('change', currentFile);

// Add Click behavior to button
document.getElementById('btnSelectFile').addEventListener('click', selectFile);

function selectFile() {
  if (inputElement.files[0]) {
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    // Reset the Input Field
    log.innerHTML += '<p>Removing file: ' + inputElement.files[0].name + '</p>'
    inputElement.value = '';
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    log.innerHTML += '<hr>'
  }

  // Once we have a clean slide, open fiel select dialog.
  inputElement.click();
};

function currentFile() {
    // If Input Element has a file
  if (inputElement.files[0]) {
    document.getElementById('currentFile').innerHTML = inputElement.files[0].name;
  }
}

</scrip>

0

Il n'y a donc aucun moyen de s'assurer à 100% qu'ils sélectionnent le même fichier, sauf si vous stockez chaque fichier et comparez-les par programme.

La façon dont vous interagissez avec les fichiers (ce que fait JS lorsque l'utilisateur «télécharge» un fichier) est HTML5 File API et JS FileReader .

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

https://scotch.io/tutorials/use-the-html5-file-api-to-work-with-files-locally-in-the-browser

Ces didacticiels vous montrent comment capturer et lire les métadonnées (stockées en tant qu'objet js) lorsqu'un fichier est téléchargé.

Créez une fonction qui déclenche «onChange» qui lira-> stockera-> comparera les métadonnées du fichier actuel aux fichiers précédents. Ensuite, vous pouvez déclencher votre événement lorsque le fichier souhaité est sélectionné.


0

Croyez-moi, cela vous aidera certainement!

// there I have called two `onchange event functions` due to some different scenario processing.

<input type="file" class="selectImagesHandlerDialog" 
    name="selectImagesHandlerDialog" 
    onclick="this.value=null;" accept="image/x-png,image/gif,image/jpeg" multiple 
    onchange="delegateMultipleFilesSelectionAndOpen(event); disposeMultipleFilesSelections(this);" />


// delegating multiple files select and open
var delegateMultipleFilesSelectionAndOpen = function (evt) {

  if (!evt.target.files) return;

  var selectedPhotos = evt.target.files;
  // some continuous source

};


// explicitly removing file input value memory cache
var disposeMultipleFilesSelections = function () {
  this.val = null;
};

J'espère que cela aidera beaucoup d'entre vous.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.