Zdarzenie wyboru pliku wejściowego HTML nie uruchamia się po wybraniu tego samego pliku


204

Czy jest szansa na wykrycie każdego wyboru pliku dokonanego przez użytkownika dla elementu HTML inputtypu file?

To było zadawane wiele razy wcześniej, ale zwykle proponowane onchangezdarzenie nie jest uruchamiane, jeśli użytkownik ponownie wybierze ten sam plik.


7
Czy Twój kod musiałby również zostać uruchomiony, jeśli użytkownik kliknie przycisk Anuluj? Można się spodziewać, że naciśnięcie Anuluj nic nie da i myślę, że większość użytkowników spodziewałaby się, że ponowne wybranie tego samego pliku miałoby taki sam efekt jak Anuluj. Nie wiem, czy jest to możliwe, czy nie, ale i tak proponuję ponownie rozważyć ten projekt.
KRyan,

1
Po anulowaniu nie powinien wystrzelić ani umożliwić wykrycia w inny sposób. Bardziej służy to usunięciu interfejsu użytkownika: jeśli po wybraniu pliku zostanie wywołana jakaś akcja, użytkownik zwykle oczekuje, że akcja się powtórzy, jeśli ponownie wybierze plik.
dronus,

Być może możemy mieć takie zachowanie, jeśli ustawimy inputwartość s na '' po zrobieniu czegoś z plikiem. Ale to też usunie widoczną nazwę pliku. Może to być w porządku, ponieważ plik jest faktycznie przetwarzany, a wynik tej akcji może pojawić się gdzie indziej.
dronus,

Plz Wyjaśnij Que Co chcesz zrobić?
Champ

1
Chcę tylko zasymulować stare aplikacje szkolne. Jeśli ponownie „otwieram” ten sam plik w aplikacji komputerowej, zwykle jest on ponownie ładowany lub jeśli plik wykonuje jakąś akcję (np. Konwertuje go na inny format), akcja jest wykonywana ponownie. Tego właśnie mogą oczekiwać użytkownicy komputerów stacjonarnych od aplikacji internetowej, ale zdarzenie filewejściowe onchangenie przypomina.
dronus

Odpowiedzi:


278

Ustaw wartość na inputdla nullkażdego onclickzdarzenia. Spowoduje to zresetowanie inputwartości i wyzwolenie onchangezdarzenia, nawet jeśli zostanie wybrana ta sama ścieżka.

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

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

Oto DEMO .

Uwaga: To normalne, jeśli plik ma przedrostek „C: \ fakepath \”. Jest to funkcja bezpieczeństwa uniemożliwiająca JavaScriptowi rozpoznanie bezwzględnej ścieżki pliku. Przeglądarka nadal wie o tym wewnętrznie.


1
Próbowałem wersji demo, ale (w przeglądarce Chrome 21) wciąż pojawia się `C: \ fakepath` +, a następnie nazwa pliku, którą wybrałem (bez ścieżki). Ostrzeżenie jest jednak wyświetlane przy każdym wyborze tego samego pliku.
Jasper de Vries

1
@JasperdeVries Jest to funkcja bezpieczeństwa uniemożliwiająca JavaScriptowi rozpoznanie bezwzględnej ścieżki pliku. Przeglądarka nadal zna wewnętrzną ścieżkę.
Brian Ustas

1
Nawiasem mówiąc, null jest jedyną dozwoloną wartością dla <input type = "file">. Jeśli więc próbujesz ustawić go jako niezdefiniowany i uzyskać wyjątek, to właśnie dlatego.
Noel Abrahams

5
Nie działa dobrze w IE11, chyba że dokonasz małej zmiany: demo .

21
Lepiej jest umieścić this.value = nullna końcu, onchangeponieważ można aktywować element wejściowy bez klikania go (za pomocą klawiatury). Możesz przechowywać, input.filesjeśli chcesz odwołać się do nich później.
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; jest konieczne tylko w Chrome, Firefox będzie działał dobrze tylko z return false;

Oto FIDDLE


2
prosty i skuteczny właśnie przetestowany w najnowszej IE i Chrome i działa jak urok. Dzięki za udostępnienie
Atul Chaudhary

8

W tym artykule pod tytułem „Korzystanie z formularza do wyboru”

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>

Dodaje detektor zdarzeń do „zmiany”, ale przetestowałem go i uruchamia się, nawet jeśli wybierzesz ten sam plik, a nie, jeśli anulujesz.


Biorąc pod uwagę potencjalnie niejednoznaczne znaczenie „zmiany” w tym przypadku, czy wypróbowałeś to w wielu przeglądarkach? Możesz określić, które z nich wypróbowałeś, tak jak w Internecie, przeglądarki nie zawsze są zgodne w tych sprawach.
Thor84no

2
Z jakiego środowiska korzystasz do testu? Moje doświadczenie z Chrome było tym, które podałem w pytaniu, changezdarzenie będzie uruchamiane tylko przy zmianach nazw plików.
dronus

7

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

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

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

Korzystanie z TypeScript

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

Dzięki za rozwiązanie.
Deepak Tekchandani

1

Rób wszystko, co chcesz, po pomyślnym załadowaniu pliku. Tuż po zakończeniu przetwarzania pliku ustaw wartość kontroli pliku na pusty łańcuch. Więc .change () będzie zawsze wywoływane, nawet jeśli nazwa pliku się zmieni, czy nie. na przykład możesz to zrobić i pracowałeś dla mnie jak urok

   $('#myFile').change(function () {
       LoadFile("myFile");//function to do processing of file.
       $('#myFile').val('');// set the value to empty of myfile control.
    });

1
handleChange({target}) {
    const files = target.files
    target.value = ''
}

1
Hej ngCourse! Odpowiedzi zawierające tylko kod mogą rozwiązać problem, ale są o wiele bardziej przydatne, jeśli wyjaśnisz, w jaki sposób je rozwiązują. Społeczność wymaga zarówno teorii, jak i kodu, aby w pełni zrozumieć twoją odpowiedź.
RBT

Chociaż ten kod może rozwiązać pytanie, w tym wyjaśnienie, w jaki sposób i dlaczego to rozwiązuje problem, naprawdę pomógłby poprawić jakość twojego postu i prawdopodobnie doprowadziłby do większej liczby głosów. Pamiętaj, że odpowiadasz na pytanie czytelników w przyszłości, a nie tylko osoby zadającej teraz pytanie. Proszę edytować swoje odpowiedzi, aby dodać wyjaśnień i dać wskazówkę co zastosować ograniczenia i założenia. Z recenzji
podwójny dźwięk

1

Wyczyszczenie wartości 0 indeksu danych wejściowych działało dla mnie . Wypróbuj poniższy kod, mam nadzieję, że to zadziała (AngularJs).

          scope.onClick = function() {
            input[0].value = "";
                input.click();
            };
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.