Jak wykryć typ wejścia = „zmiana” pliku dla tego samego pliku?

131

Chcę uruchomić zdarzenie, gdy użytkownik wybierze plik. Robiąc to ze .changezdarzeniem, działa, jeśli użytkownik zmienia plik za każdym razem.

Ale chcę uruchomić zdarzenie, jeśli użytkownik ponownie wybierze ten sam plik.

  1. Plik wyboru użytkownika A.jpg(wywołania zdarzenia)
  2. Plik wyboru użytkownika B.jpg(wywołania zdarzenia)
  3. Plik wyboru użytkownika B.jpg(zdarzenie się nie uruchamia, chcę go uruchomić)

Jak mogę to zrobić?

Gadonski
źródło

Odpowiedzi:

78

Możesz to oszukać. Usuń element file i dodaj go w tym samym miejscu changewydarzenia. Spowoduje to usunięcie ścieżki pliku, dzięki czemu będzie można ją zmieniać za każdym razem.

Przykład na jsFiddle.

Lub możesz po prostu użyć .prop("value", ""), zobacz ten przykład na jsFiddle .

  • jQuery 1.6+ prop
  • Wcześniejsze wersje attr
BrunoLM
źródło
@Pekka: Niezupełnie. Ale może to po prostu dostosować. Powiedzmy, że musi opublikować plik. Po poście może wywołać funkcję js, która usunie i doda nowy selektor pliku. To jest wykonalne.
BrunoLM
3
pamiętaj, że jeśli użyjesz .attr("value", "")lub .val("")(jak sugeruje @ wagner-leonardi poniżej), Internet Explorer uruchomi zdarzenie zmiany, podczas gdy chrome nie
fadomire
4
ponieważ „wartość” jest właściwością, a nie atrybutem danych wejściowych, zalecane użycie jQuery to.prop("value", "")
Roger Barreto
70

Jeśli próbowałeś .attr("value", "")i nie działałeś, nie panikuj (tak jak ja)

po prostu zrób to .val("")i będzie działać dobrze

Wagner Leonardi
źródło
49

Możesz po prostu ustawić zerowanie ścieżki pliku za każdym razem, gdy użytkownik kliknie kontrolkę. Teraz, nawet jeśli użytkownik wybierze ten sam plik, zostanie wyzwolone zdarzenie onchange .

<input id="file" onchange="file_changed(this)" onclick="this.value=null;" type="file" accept="*/*" />
Mariusz Wiazowski
źródło
2
Potrzebowałem takiego rozwiązania. Jest naprawdę krótki i wykonuje swoją pracę. Miło myślący Mariusz Wiazowski.
Jay Dharmendra Solanki
Innym rozwiązaniem jest zmiana wartości po zmianie tagu wejściowego. Ale nie spodziewamy się zmiany wartości po wybraniu pliku.
songgeb
1
Fajnie, o wiele lepsze niż usuwanie i ponowne dodawanie elementu w dom, dzięki
David Dal Busco
24

Użyj zdarzenia onClick, aby wyczyścić wartość wejścia docelowego za każdym razem, gdy użytkownik kliknie pole. Zapewnia to, że zdarzenie onChange zostanie wyzwolone również dla tego samego pliku. Pracował dla mnie :)

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

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

Korzystanie z języka TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}
Prawo Trafalgara
źródło
17

Mam to do pracy, usuwając wartość wejściową pliku onClick, a następnie publikując plik onChange. Dzięki temu użytkownik może wybrać ten sam plik dwa razy z rzędu i nadal uruchamiać zdarzenie zmiany w celu przesłania go na serwer. Mój przykład używa wtyczki formularza jQuery .

$('input[type=file]').click(function(){
    $(this).attr("value", "");
})  
$('input[type=file]').change(function(){
    $('#my-form').ajaxSubmit(options);      
})
Braitsch
źródło
onClickodpala wcześniej onChange, więc ta metoda działa na mnie świetnie.
iplus26
8

Ta praca dla mnie

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

źródło
1
Myślę, że miałeś na myśli coś takiego jak function () {this.value = null; return false; }
Jacek Pietal 31.07.14
7

Rozwiązanie VueJs

<input
                type="file"
                style="display: none;"
                ref="fileInput"
                accept="*"
                @change="onFilePicked"
                @click="$refs.fileInput.value=null"
>
Micheal C Wallas
źródło
1
Dziękuję za tę odpowiedź
Coisox
5

Inspirując się @braitsch, użyłem w moim AngularJS2 następujących elementów 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);
    }
}

Tutaj onClick(event)mnie uratował :-)

MKJ
źródło
3

Prawdopodobnie najłatwiejszą rzeczą, jaką możesz zrobić, jest ustawienie wartości na pusty ciąg. To zmusza go do „zmiany” pliku za każdym razem, nawet jeśli ten sam plik zostanie wybrany ponownie.

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

Lakoniczny
źródło
3

Oto rozwiązanie React-y, które znalazłem, które zadziałało:

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

Heckmann
źródło
2

Jeśli nie chcesz używać jQuery

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

Działa dobrze w przeglądarce Firefox, ale w przeglądarce Chrome musisz dodać this.value=null;po alercie.

elshnkhll
źródło
2

Domyślnie właściwość value elementu wejściowego jest czyszczona po wybraniu plików, jeśli dane wejściowe mają wiele atrybutów. Jeśli nie wyczyścisz tej właściwości, zdarzenie „change” nie zostanie uruchomione, jeśli wybierzesz ten sam plik. Możesz zarządzać tym zachowaniem za pomocą multipleatrybutu.

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

Odniesienie

Pulkit Aggarwal
źródło
1

Nie możesz changetutaj rozpalić ognia (poprawne zachowanie, ponieważ nic się nie zmieniło). Jednak możesz również związać click... chociaż może to wystrzelić zbyt często ... jednak między nimi nie ma zbyt wiele środka.

$("#fileID").bind("click change", function() {
  //do stuff
});
Nick Craver
źródło
Wygląda na to, że po prostu powtarzasz jego słowa i .click()nie jest to „ogień po ponownym wybraniu”.
BrunoLM
@BrunoLM - Nie, nie jest ... ale myślę, że przeczytałeś część, w której mówię, że nie możesz tego zrobić, clickjest tak blisko, jak to tylko możliwe.
Nick Craver
1

Utwórz dla danych wejściowych zdarzenie kliknięcia i zdarzenie zmiany. Zdarzenie click opróżnia dane wejściowe, a zdarzenie change zawiera kod, który chcesz wykonać.

Tak więc zdarzenie click zostanie puste po kliknięciu przycisku wejściowego (przed otwarciem okna wyboru pliku), w związku z czym zdarzenie zmiany będzie zawsze wyzwalane po wybraniu pliku.

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

hoi ja
źródło
0

Możesz użyć, form.reset()aby wyczyścić listę plików wejściowych files. Spowoduje to zresetowanie wszystkich pól do wartości domyślnych, ale w wielu przypadkach możesz używać tylko parametru input type = 'file' w formularzu do przesyłania plików. W tym rozwiązaniu nie ma potrzeby klonowania elementu i ponownego podpinania zdarzeń.

Dzięki philiplehmann

Rui Nunes
źródło
0

Natknąłem się na ten sam problem, przeczytałem powyższe rozwiązania, ale nie dostały żadnego dobrego wyjaśnienia, co tak naprawdę się dzieje.

To rozwiązanie, które napisałem https://jsfiddle.net/r2wjp6u8/ nie robi wielu zmian w drzewie DOM, po prostu zmienia wartości pola wejściowego. Z punktu widzenia wydajności powinno być trochę lepiej.

Link do skrzypiec: 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>
Ballpin
źródło
0

Tak więc nie ma sposobu, aby w 100% upewnić się, że wybierają ten sam plik, chyba że zapiszesz każdy plik i porównasz je programowo.

Sposób interakcji z plikami (co robi JS, gdy użytkownik „przesyła” plik) to HTML5 File API i 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

Te samouczki pokazują, jak przechwytywać i odczytywać metadane (przechowywane jako obiekt js) podczas przesyłania pliku.

Utwórz funkcję uruchamiającą „onChange”, która odczyta-> zapisze-> porówna metadane bieżącego pliku z poprzednimi plikami. Następnie możesz wywołać zdarzenie po wybraniu żądanego pliku.

Stephanie Schellin
źródło
0

Uwierz mi, to na pewno ci pomoże!

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

Mam nadzieję, że to pomoże wielu z was.

ArifMustafa
źródło