Wie erkenne ich den Eingabetyp = Datei "Änderung" für dieselbe Datei?


131

Ich möchte ein Ereignis auslösen, wenn der Benutzer eine Datei auswählt. Bei einem .changeEreignis funktioniert dies, wenn der Benutzer die Datei jedes Mal ändert.

Ich möchte das Ereignis jedoch auslösen, wenn der Benutzer dieselbe Datei erneut auswählt.

  1. Benutzerauswahldatei A.jpg(Ereignis wird ausgelöst)
  2. Benutzerauswahldatei B.jpg(Ereignis wird ausgelöst)
  3. Benutzerauswahldatei B.jpg(Ereignis wird nicht ausgelöst, ich möchte, dass es ausgelöst wird)

Wie kann ich es tun?

Antworten:


78

Sie können es austricksen. Entfernen Sie das Dateielement und fügen Sie es bei changeEreignis an derselben Stelle hinzu . Der Dateipfad wird gelöscht, sodass er jedes Mal geändert werden kann.

Beispiel auf jsFiddle.

Oder Sie können einfach verwenden .prop("value", ""), siehe dieses Beispiel auf jsFiddle .

  • jQuery 1.6+ prop
  • Frühere Versionen attr

@ Pekka: Nicht genau. Aber er kann es einfach anpassen. Angenommen, er muss die Datei veröffentlichen. Nach dem Post kann er eine js-Funktion aufrufen, die den neuen Datei-Selektor entfernt und hinzufügt. Es ist machbar.
BrunoLM

3
Beachten Sie, dass bei Verwendung von .attr("value", "")oder .val("")(wie von @ wagner-leonardi unten vorgeschlagen) der Internet Explorer das Änderungsereignis
auslöst,

4
Da "Wert" eine Eigenschaft und kein Attribut der Eingabe ist, wäre die empfohlene Verwendung von jQuery.prop("value", "")
Roger Barreto

70

Wenn Sie versucht haben .attr("value", "")und nicht gearbeitet haben, geraten Sie nicht in Panik (wie ich)

Tun Sie es .val("")stattdessen und es wird gut funktionieren


49

Sie können den Dateipfad einfach jedes Mal auf Null setzen, wenn der Benutzer auf das Steuerelement klickt. Selbst wenn der Benutzer dieselbe Datei auswählt, wird das Ereignis onchange ausgelöst.

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

2
Ich brauchte eine solche Lösung. Es ist wirklich kurz und erledigt die Arbeit. Gut denkender Mariusz Wiazowski.
Jay Dharmendra Solanki

Eine andere Lösung besteht darin, den Wert zu ändern, wenn sich das Eingabe-Tag ändert. Wir erwarten jedoch nicht, dass der Wert nach Auswahl einer Datei geändert wird.
Songgeb

1
Cool, viel besser als das Element im Dom wieder zu entfernen und hinzuzufügen, danke
David Dal Busco

24

Verwenden Sie das Ereignis onClick, um den Wert der Zieleingabe jedes Mal zu löschen, wenn der Benutzer auf das Feld klickt. Dadurch wird sichergestellt, dass das Ereignis onChange auch für dieselbe Datei ausgelöst wird. Arbeitete für mich :)

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

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

Verwenden von TypeScript

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

17

Ich habe dies zum Laufen gebracht, indem ich den Dateieingabewert onClick gelöscht und dann die Datei onChange gepostet habe. Auf diese Weise kann der Benutzer dieselbe Datei zweimal hintereinander auswählen und trotzdem das Änderungsereignis auslösen, um es auf dem Server zu veröffentlichen. In meinem Beispiel wird das jQuery-Formular-Plugin verwendet .

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

onClickfeuert vorher onChange, also funktioniert diese Methode großartig für mich.
iplus26

8

Diese Arbeit für mich

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

1
Ich denke du meintest so etwas wie function () {this.value = null; falsch zurückgeben; }
Jacek Pietal

7

VueJs Lösung

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

1
Vielen Dank für diese Variation Antwort
Coisox

5

Inspiriert von @braitsch habe ich in meinem AngularJS2 Folgendes verwendet 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);
    }
}

Hier hat onClick(event)mich das gerettet :-)


3

Wahrscheinlich ist es am einfachsten, den Wert auf eine leere Zeichenfolge zu setzen. Dies zwingt es, die Datei jedes Mal zu ändern, selbst wenn dieselbe Datei erneut ausgewählt wird.

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


3

Hier ist die React-y-Way-Lösung, die für mich funktioniert hat:

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


2

Wenn Sie jQuery nicht verwenden möchten

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

Es funktioniert gut in Firefox, aber für Chrome müssen Sie this.value=null;nach der Warnung hinzufügen .


2

Standardmäßig wird die value-Eigenschaft des Eingabeelements nach Auswahl der Dateien gelöscht, wenn die Eingabe mehrere Attribute aufweist. Wenn Sie diese Eigenschaft nicht bereinigen, wird das Ereignis "Ändern" nicht ausgelöst, wenn Sie dieselbe Datei auswählen. Sie können dieses Verhalten mithilfe von multipleAttributen verwalten.

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

Referenz


1

Sie können hier kein changeFeuer machen (korrektes Verhalten, da sich nichts geändert hat). Sie könnten jedoch auch binden click... obwohl dies zu oft feuert ... gibt es jedoch nicht viel Mittelweg zwischen den beiden.

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

Es scheint, dass Sie nur seine Worte wiederholen und .click()nicht "Feuer bei erneuter Auswahl" sind.
BrunoLM

@BrunoLM - Nein, es ist nicht ... aber ich denke, Sie lesen den Teil durch, in dem ich sage, dass Sie das nicht können, der clickist so nah wie es nur geht.
Nick Craver

1

Erstellen Sie für die Eingabe ein Klickereignis und ein Änderungsereignis. Das Klickereignis leert die Eingabe und das Änderungsereignis enthält den Code, den Sie ausführen möchten.

Das Klickereignis wird also leer, wenn Sie auf die Eingabeschaltfläche klicken (bevor das Fenster zum Auswählen von Dateien geöffnet wird). Daher wird das Änderungsereignis immer ausgelöst, wenn Sie eine Datei auswählen.

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

Sie können damit form.reset()die filesListe der Dateieingaben löschen . Dadurch werden alle Felder auf die Standardwerte zurückgesetzt. In vielen Fällen verwenden Sie jedoch möglicherweise nur den Eingabetyp = 'Datei' in einem Formular, um Dateien hochzuladen. In dieser Lösung ist es nicht erforderlich, das Element zu klonen und Ereignisse erneut zu verknüpfen.

Danke an philiplehmann


0

Ich bin auf dasselbe Problem gestoßen, ich habe die obigen Lösungen durchgesehen, aber sie haben keine gute Erklärung dafür bekommen, was wirklich geschah.

Diese Lösung habe ich geschrieben https://jsfiddle.net/r2wjp6u8/ ändert nicht viele Änderungen im DOM-Baum, sondern nur die Werte des Eingabefelds. Unter Leistungsaspekten sollte es etwas besser sein.

Link zur Geige: 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

Es gibt also keine Möglichkeit, zu 100% sicher zu sein, dass sie dieselbe Datei auswählen, es sei denn, Sie speichern jede Datei und vergleichen sie programmgesteuert.

Die Art und Weise, wie Sie mit Dateien interagieren (was JS tut, wenn der Benutzer eine Datei hochlädt), ist die HTML5-Datei-API und JS FileReader .

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

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

Diese Tutorials zeigen Ihnen, wie Sie die Metadaten (als js-Objekt gespeichert) erfassen und lesen, wenn eine Datei hochgeladen wird.

Erstellen Sie eine Funktion, die 'onChange' auslöst und die Metadaten der aktuellen Datei mit den vorherigen Dateien liest-> speichern-> vergleicht. Dann können Sie Ihr Ereignis auslösen, wenn die gewünschte Datei ausgewählt ist.


0

Glauben Sie mir, es wird Ihnen auf jeden Fall helfen!

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

Hoffe das wird vielen von euch helfen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.