Come rilevare input type = file "change" per lo stesso file?


131

Voglio lanciare un evento quando l'utente seleziona un file. In questo modo con l' .changeevento funziona se l'utente cambia il file ogni volta.

Ma voglio lanciare l'evento se l'utente seleziona di nuovo lo stesso file.

  1. File di selezione utente A.jpg(evento attivato)
  2. File di selezione utente B.jpg(evento attivato)
  3. File di selezione dell'utente B.jpg(l'evento non si attiva, voglio che venga attivato)

Come posso farlo?

Risposte:


78

Puoi ingannarlo. Rimuovi l'elemento del file e aggiungilo nello stesso posto changedell'evento. Cancella il percorso del file rendendolo ogni volta modificabile.

Esempio su jsFiddle.

Oppure puoi semplicemente usare .prop("value", ""), vedi questo esempio su jsFiddle .

  • jQuery 1.6+ prop
  • Versioni precedenti attr

@Pekka: non esattamente. Ma può solo adattarlo. Diciamo che deve pubblicare il file. Dopo il post può chiamare una funzione js che rimuoverà e aggiungerà il nuovo selettore di file. È fattibile.
BrunoLM,

3
tieni presente che quando utilizzi .attr("value", "")o .val("")(come suggerito da @ wagner-leonardi di seguito) Internet Explorer genererà l'evento change mentre Chrome non lo fa
fadomire

4
poiché "valore" è una proprietà e non un attributo di input, l'utilizzo jQuery consigliato sarebbe.prop("value", "")
Roger Barreto,

70

Se hai provato .attr("value", "")e non hai funzionato, non farti prendere dal panico (come ho fatto io)

fai .val("")invece invece e funzionerà bene


49

È possibile semplicemente impostare su null il percorso del file ogni volta che l'utente fa clic sul controllo. Ora, anche se l'utente seleziona lo stesso file, verrà attivato l'evento onchange .

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

2
Avevo bisogno di una soluzione come questa. È davvero breve e porta a termine il lavoro. Bel pensiero Mariusz Wiazowski.
Jay Dharmendra Solanki,

Un'altra soluzione è quella di modificare il valore quando viene modificato il tag di input. Ma non prevediamo che il valore venga modificato dopo aver selezionato un file.
Songgeb,

1
Bene, molto meglio che rimuovere e aggiungere di nuovo l'elemento nel dom, grazie
David Dal Busco,

24

Utilizzare l'evento onClick per cancellare il valore dell'input target, ogni volta che l'utente fa clic sul campo. Ciò garantisce che l'evento onChange verrà attivato anche per lo stesso file. Ha funzionato per me :)

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

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

Utilizzando TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}

17

Ho ottenuto che funzioni cancellando il valore di input del file su Click e quindi pubblicando il file su Exchange. Ciò consente all'utente di selezionare lo stesso file due volte di seguito e di avere ancora il fuoco dell'evento change da pubblicare sul server. Il mio esempio usa il plugin del modulo jQuery .

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

onClickspara prima onChange, quindi questo metodo funziona benissimo per me.
iplus26

8

Questo lavoro per me

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

1
immagino volessi dire qualcosa come function () {this.value = null; restituire false; }
Jacek Pietal,

7

VueJs solution

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

1
Grazie per questa risposta variazione
Coisox

5

Ispirandomi a @braitsch ho usato quanto segue nel mio 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);
    }
}

Qui onClick(event)mi ha salvato :-)


3

Probabilmente la cosa più semplice che puoi fare è impostare il valore su una stringa vuota. Ciò lo costringe a "cambiare" il file ogni volta anche se lo stesso file viene nuovamente selezionato.

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


3

Ecco la soluzione React-y che ho trovato che ha funzionato per me:

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


2

Se non vuoi usare jQuery

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

Funziona bene in Firefox, ma per Chrome è necessario aggiungere this.value=null;dopo l'avviso.


2

Per impostazione predefinita, la proprietà value dell'elemento input è deselezionata dopo la selezione dei file se l'input ha più attributi. Se non si pulisce questa proprietà, l'evento "modifica" non verrà generato se si seleziona lo stesso file. È possibile gestire questo comportamento utilizzando l' multipleattributo.

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

Riferimento


1

Non puoi changeaccendere il fuoco qui (comportamento corretto, poiché nulla è cambiato). Tuttavia, potresti anche legare click... anche se questo potrebbe sparare troppo spesso ... non c'è molta via di mezzo tra i due però.

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

Sembra che tu stia solo ripetendo le sue parole e .click()non è "fuoco su ri-selezionare".
BrunoLM,

@BrunoLM - No, non lo è ... ma penso che tu abbia letto la parte in cui dico che non puoi farlo, clickè il più vicino possibile.
Nick Craver

1

Crea per l'input un evento click e un evento change. L'evento click svuota l'input e l'evento change contiene il codice che si desidera eseguire.

Quindi l'evento click si svuota quando si fa clic sul pulsante di input (prima che si apra la finestra di selezione del file), pertanto l'evento change si attiverà sempre quando si seleziona un file.

$("#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

È possibile utilizzare form.reset()per cancellare l' fileselenco di input del file . Ciò ripristinerà tutti i campi ai valori predefiniti, ma in molti casi potresti utilizzare solo l'input type = 'file' in un modulo per caricare comunque i file. In questa soluzione non è necessario clonare l'elemento e riagganciare nuovamente gli eventi.

Grazie a Philiplehmann


0

Mi sono imbattuto nello stesso problema, ho esaminato le soluzioni sopra ma non hanno avuto una buona spiegazione di ciò che stava realmente accadendo.

Questa soluzione che ho scritto https://jsfiddle.net/r2wjp6u8/ non fa molte modifiche nella struttura DOM, cambia solo i valori del campo di input. Dal punto di vista delle prestazioni dovrebbe essere leggermente migliore.

Link al violino: 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

Pertanto, non è possibile accertarsi che stiano selezionando lo stesso file al 100% a meno che non si memorizzi ciascun file e lo si confronti a livello di codice.

Il modo in cui interagisci con i file (cosa fa JS quando l'utente "carica" ​​un file) è l' API di file HTML5 e JR 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

Queste esercitazioni mostrano come acquisire e leggere i metadati (memorizzati come oggetto js) quando viene caricato un file.

Crea una funzione che attiva 'onChange' che leggerà-> store-> confronta i metadati del file corrente con i file precedenti. Quindi puoi attivare il tuo evento quando viene selezionato il file desiderato.


0

Credimi, ti aiuterà sicuramente!

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

Spero che questo possa aiutare molti di voi ragazzi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.