Wie erkennt man, wenn bei der Dateieingabe auf Abbrechen geklickt wird?

112

Wie kann ich erkennen, wenn der Benutzer eine Dateieingabe mithilfe einer HTML-Dateieingabe abbricht?

Mit onChange kann ich erkennen, wann sie eine Datei auswählen, aber ich möchte auch wissen, wann sie abbrechen (schließen Sie den Dateiauswahldialog, ohne etwas auszuwählen).

Ppp
quelle
Sie können auch erkennen, ob jemand die Datei auswählt und dann versucht, eine zu senden, aber abzubrechen. Sie werden leere.target.files
jcubic

Antworten:

45

Obwohl dies keine direkte Lösung ist und auch insofern schlecht, als es nur (soweit ich es getestet habe) mit Onfocus funktioniert (was eine ziemlich einschränkende Ereignisblockierung erfordert), können Sie dies mit den folgenden Ergebnissen erreichen:

document.body.onfocus = function(){ /*rock it*/ }

Das Schöne daran ist, dass Sie es rechtzeitig mit dem Dateiereignis anhängen / trennen können, und es scheint auch mit versteckten Eingaben gut zu funktionieren (ein klarer Vorteil, wenn Sie eine visuelle Problemumgehung für den beschissenen Standardeingabetyp verwenden = ' Datei'). Danach müssen Sie nur noch herausfinden, ob sich der Eingabewert geändert hat.

Ein Beispiel:

var godzilla = document.getElementById('godzilla')

godzilla.onclick = charge

function charge()
{
    document.body.onfocus = roar
    console.log('chargin')
}

function roar()
{
    if(godzilla.value.length) alert('ROAR! FILES!')
    else alert('*empty wheeze*')
    document.body.onfocus = null
    console.log('depleted')
}

Sehen Sie es in Aktion: http://jsfiddle.net/Shiboe/yuK3r/6/

Leider scheint es nur in Webkit-Browsern zu funktionieren. Vielleicht kann jemand anderes die Firefox / IE-Lösung herausfinden

Shiboe
quelle
Ich wollte nicht, dass das Fokusereignis jedes Mal ausgelöst wird, also wollte ich es verwenden addEventListener("focus",fn,{once: true}). Ich konnte es jedoch überhaupt nicht zum Feuern bringen document.body.addEventListener. Ich weiß nicht warum. Stattdessen habe ich das gleiche Ergebnis mit window.addEventListener.
WoodenKitty
3
Dies funktioniert in Firefox und Edge bei mir nicht. Doch für das hört mousemoveauf Ereignis window.document zusätzlich zu hören focusauf windowscheint überall zu arbeiten (zumindest in modernen Browsern, ich kümmere mich nicht um Vergangenheits Jahrzehnt Wracks). Grundsätzlich kann für diese Aufgabe jedes Interaktionsereignis verwendet werden, das durch einen geöffneten Dialog zum Öffnen von Dateien blockiert wird.
John Weisz
@WoodenKitty Wie haben Sie dies mit dem addEventListener implementiert? Ich versuche dies in eckigen und das Dokument zu tun. Auch für mich arbeitet niemand
Terrance Jackson
Dies funktioniert nicht bei versteckten Eingabefeldern.
Sebastian
20

Das kannst du nicht.

Das Ergebnis des Dateidialogs wird dem Browser nicht angezeigt.

Oded
quelle
Kann überprüft werden, ob die Dateiauswahl geöffnet ist oder nicht?
Ppp
1
@Ppp - Nein. Der Browser sagt Ihnen das nicht.
Oded
6
"Das Ergebnis des Dateidialogs wird dem Browser nicht angezeigt." Dies gilt nicht, wenn der Dialog durch Auswahl einer Datei geschlossen wird.
Trevor
3
Die durch die Verwendung des Dateidialogs ausgelöste Änderung wird dem Browser angezeigt. Wenn keine Datei ausgewählt ist und anschließend keine Datei ausgewählt wird, hat sich nichts geändert, sodass kein changeEreignis ausgelöst wird.
John Weisz
1
Wenn eine Datei bereits ausgewählt ist und Sie dieselbe Datei erneut auswählen, wird auch dafür kein changeEreignis ausgelöst.
Patrick Roberts
16

Also werde ich meinen Hut in diese Frage werfen, da ich eine neuartige Lösung gefunden habe. Ich habe eine Progressive Web App, mit der Benutzer Fotos und Videos aufnehmen und hochladen können. Wir verwenden WebRTC, wenn möglich, greifen jedoch auf HTML5-Dateiauswahl für Geräte mit weniger Unterstützung zurück * Husten Safari Husten *. Wenn Sie speziell an einer mobilen Webanwendung für Android / iOS arbeiten, die die native Kamera verwendet, um Fotos / Videos direkt aufzunehmen, ist dies die beste Lösung, die mir begegnet ist.

Der Kern dieses Problems besteht darin, dass beim Laden der Seite das fileist null, aber wenn der Benutzer den Dialog öffnet und auf "Abbrechen" drückt, das fileist immer noch null, daher wurde es nicht "geändert", sodass kein "Ändern" -Ereignis ausgelöst wird. Für Desktops ist dies nicht schlecht, da die meisten Desktop-Benutzeroberflächen nicht davon abhängig sind, zu wissen, wann ein Abbruch aufgerufen wird. Mobile Benutzeroberflächen, die die Kamera zum Aufnehmen eines Fotos / Videos aufrufen, sind jedoch sehr davon abhängig, zu wissen, wann ein Abbruch gedrückt wird.

Ich habe das document.body.onfocusEreignis ursprünglich verwendet , um zu erkennen, wann der Benutzer von der Dateiauswahl zurückgekehrt ist. Dies funktionierte für die meisten Geräte, aber iOS 11.3 hat es unterbrochen, da dieses Ereignis nicht ausgelöst wird.

Konzept

Meine Lösung hierfür ist * shudder *, um das CPU-Timing zu messen und festzustellen, ob sich die Seite derzeit im Vordergrund oder im Hintergrund befindet. Auf Mobilgeräten wird der aktuell im Vordergrund stehenden App Verarbeitungszeit zugewiesen. Wenn eine Kamera sichtbar ist, stiehlt sie die CPU-Zeit und setzt den Browser außer Kraft. Alles, was wir tun müssen, ist zu messen, wie viel Verarbeitungszeit unsere Seite hat, wenn die Kamera startet, wird unsere verfügbare Zeit drastisch sinken. Wenn die Kamera geschlossen wird (entweder abgebrochen oder auf andere Weise), wird unsere verfügbare Zeitspitze wieder erhöht.

Implementierung

Wir können das CPU-Timing messen, indem wir setTimeout()einen Rückruf in X Millisekunden aufrufen und dann messen, wie lange es gedauert hat, ihn tatsächlich aufzurufen. Der Browser wird es nie genau nach X Millisekunden aufrufen , aber wenn es in der Nähe vernünftig ist, müssen wir im Vordergrund stehen. Wenn der Browser sehr weit entfernt ist (über 10x langsamer als angefordert), müssen wir uns im Hintergrund befinden. Eine grundlegende Implementierung davon ist wie folgt:

function waitForCameraDismiss() {
  const REQUESTED_DELAY_MS = 25;
  const ALLOWED_MARGIN_OF_ERROR_MS = 25;
  const MAX_REASONABLE_DELAY_MS =
      REQUESTED_DELAY_MS + ALLOWED_MARGIN_OF_ERROR_MS;
  const MAX_TRIALS_TO_RECORD = 10;

  const triggerDelays = [];
  let lastTriggerTime = Date.now();

  return new Promise((resolve) => {
    const evtTimer = () => {
      // Add the time since the last run
      const now = Date.now();
      triggerDelays.push(now - lastTriggerTime);
      lastTriggerTime = now;

      // Wait until we have enough trials before interpreting them.
      if (triggerDelays.length < MAX_TRIALS_TO_RECORD) {
        window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
        return;
      }

      // Only maintain the last few event delays as trials so as not
      // to penalize a long time in the camera and to avoid exploding
      // memory.
      if (triggerDelays.length > MAX_TRIALS_TO_RECORD) {
        triggerDelays.shift();
      }

      // Compute the average of all trials. If it is outside the
      // acceptable margin of error, then the user must have the
      // camera open. If it is within the margin of error, then the
      // user must have dismissed the camera and returned to the page.
      const averageDelay =
          triggerDelays.reduce((l, r) => l + r) / triggerDelays.length
      if (averageDelay < MAX_REASONABLE_DELAY_MS) {
        // Beyond any reasonable doubt, the user has returned from the
        // camera
        resolve();
      } else {
        // Probably not returned from camera, run another trial.
        window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
      }
    };
    window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
  });
}

Ich habe dies auf der neuesten Version von iOS und Android getestet und die native Kamera durch Festlegen der Attribute für das <input />Element aufgerufen.

<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />

Das klappt eigentlich viel besser als ich erwartet hatte. Es werden 10 Versuche ausgeführt, indem angefordert wird, dass ein Timer in 25 Millisekunden aufgerufen wird. Anschließend wird gemessen, wie lange das Aufrufen tatsächlich gedauert hat. Wenn der Durchschnitt von 10 Versuchen weniger als 50 Millisekunden beträgt, gehen wir davon aus, dass wir im Vordergrund stehen müssen und die Kamera weg ist. Wenn es größer als 50 Millisekunden ist, müssen wir immer noch im Hintergrund sein und sollten weiter warten.

Einige zusätzliche Details

Ich habe setTimeout()eher verwendet, als setInterval()weil letztere mehrere Aufrufe in die Warteschlange stellen können, die unmittelbar nacheinander ausgeführt werden. Dies könnte das Rauschen in unseren Daten drastisch erhöhen, daher habe ich mich daran gehalten, setTimeout()obwohl dies etwas komplizierter ist.

Diese bestimmten Zahlen haben bei mir gut funktioniert, obwohl ich mindestens einmal einen Fall gesehen habe, in dem die Kameraentlassung vorzeitig erkannt wurde. Ich glaube, das liegt daran, dass sich die Kamera möglicherweise nur langsam öffnet und das Gerät möglicherweise 10 Versuche ausführt, bevor es tatsächlich in den Hintergrund tritt. Das Hinzufügen weiterer Versuche oder das Warten von 25 bis 50 Millisekunden vor dem Starten dieser Funktion kann eine Problemumgehung sein.

Desktop

Leider funktioniert dies bei Desktop-Browsern nicht wirklich. Theoretisch ist der gleiche Trick möglich, da die aktuelle Seite Vorrang vor Hintergrundseiten hat. Viele Desktops verfügen jedoch über genügend Ressourcen, um die Seite auch im Hintergrund mit voller Geschwindigkeit laufen zu lassen, sodass diese Strategie in der Praxis nicht wirklich funktioniert.

Alternativlösungen

Eine alternative Lösung, die nicht viele Leute erwähnen, die ich erforscht habe, war das Verspotten von a FileList. Wir beginnen mit nullin <input />und wenn der Benutzer die Kamera öffnet und abbricht, kehren sie zurück null, was keine Änderung darstellt und kein Ereignis auslöst. Eine Lösung wäre, dem <input />Start der Seite eine Dummy-Datei zuzuweisen , daher nullwäre die Einstellung auf eine Änderung, die das entsprechende Ereignis auslösen würde.

Leider gibt es keine offizielle Möglichkeit, eine zu erstellen FileList, und das <input />Element erfordert eine FileListbestimmte und akzeptiert keinen anderen Wert als diese null. Natürlich können FileListObjekte nicht direkt konstruiert werden, um ein altes Sicherheitsproblem zu lösen, das anscheinend nicht mehr relevant ist. Die einzige Möglichkeit, einen außerhalb eines <input />Elements zu finden, besteht darin, einen Hack zu verwenden, der Daten kopiert und einfügt, um ein Zwischenablageereignis zu fälschen, das ein FileListObjekt enthalten kann (Sie fälschen im Grunde ein Drag-and-Drop-A-File-On -Ihre-Website-Veranstaltung). Dies ist in Firefox möglich, jedoch nicht für iOS Safari. Daher war dies für meinen speziellen Anwendungsfall nicht möglich.

Browser, bitte ...

Unnötig zu sagen, dass dies offensichtlich lächerlich ist. Die Tatsache, dass Webseiten keine Benachrichtigung erhalten, dass sich ein kritisches UI-Element geändert hat, ist einfach lächerlich. Dies ist wirklich ein Fehler in der Spezifikation, da es nie für eine Vollbild-Benutzeroberfläche für die Medienerfassung gedacht war und das Nichtauslösen des "Änderungs" -Ereignisses technisch der Spezifikation entspricht.

Können Browser-Anbieter jedoch bitte die Realität erkennen? Dies könnte entweder mit einem neuen "erledigt" -Ereignis gelöst werden, das ausgelöst wird, auch wenn keine Änderung auftritt, oder Sie könnten sowieso nur "Änderung" auslösen. Ja, das wäre gegen die Spezifikation, aber es ist für mich trivial, ein Änderungsereignis auf der JavaScript-Seite zu dedupieren, aber grundsätzlich unmöglich, mein eigenes "erledigtes" Ereignis zu erfinden. Auch meine Lösung ist eigentlich nur Heuristik, wenn keine Garantie für den Zustand des Browsers besteht.

Derzeit ist diese API für mobile Geräte grundsätzlich unbrauchbar, und ich denke, eine relativ einfache Browseränderung könnte dies für Webentwickler unendlich einfacher machen * tritt aus der Seifenkiste *.

Douglas Parker
quelle
7

Wenn Sie eine Datei auswählen und auf Öffnen / Abbrechen klicken, sollte das inputElement den Fokus verlieren blur. Angenommen, die Initiale valuevon inputist leer, würde jeder nicht leere Wert in Ihrem blurHandler ein OK anzeigen, und ein leerer Wert würde Abbrechen bedeuten.

UPDATE: Das blurwird nicht ausgelöst, wenn das inputausgeblendet ist. Daher kann dieser Trick bei IFRAME-basierten Uploads nicht verwendet werden, es sei denn, Sie möchten das vorübergehend anzeigen input.

zvolkov
quelle
3
In Firefox 10 Beta und Chrome 16 blurwird nicht ausgelöst, wenn Sie eine Datei auswählen. Ich habe es nicht in anderen Browsern versucht.
Blaise
1
Das funktioniert nicht - Unschärfe bei der Eingabe wird sofort nach dem Klicken ausgelöst. Chrome 63.0.3239.84 x64 unter Win7.
Qwertiy
7
/* Tested on Google Chrome */
$("input[type=file]").bind("change", function() {
    var selected_file_name = $(this).val();
    if ( selected_file_name.length > 0 ) {
        /* Some file selected */
    }
    else {
        /* No file selected or cancel/close
           dialog button clicked */
        /* If user has select a file before,
           when they submit, it will treated as
           no file selected */
    }
});
Rizky
quelle
6
Haben Sie überprüft, ob Ihre elseAussage jemals bewertet wird?
Jayarjo
Soweit ich mich erinnere, als ich diese Antwort schrieb, wird der Benutzer, wenn er eine Datei auswählt und dann die Datei erneut auswählt (aber dann abbricht), als keine ausgewählte Datei behandelt. Ich verwende die Warnung nur bei der Variablen selected_file_name, um sie zu testen. Jedenfalls habe ich es seitdem nicht mehr getestet.
Rizky
4
Nach einigen browserübergreifenden Tests kann ich sagen, dass Firefox beim Abbrechen weder ein Änderungsereignis auslöst noch die vorhandenen Dateien löscht, die beim erneuten Öffnen und Abbrechen beim zweiten Klicken ausgewählt wurden. Seltsam, was?
mix3d
7

Die meisten dieser Lösungen funktionieren bei mir nicht.

Das Problem ist, dass Sie nie wissen, welches Ereignis zuerst ausgelöst wird, clickoder change? Sie können keine Reihenfolge annehmen, da dies wahrscheinlich von der Implementierung des Browsers abhängt.

Zumindest in Opera und Chrome (Ende 2015) clickwird kurz vor dem "Füllen" der Eingabe mit Dateien ausgelöst, sodass Sie nie wissen, wie lange files.length != 0es dauert click, bis Sie die Auslösung verzögern change.

Hier ist Code:

var inputfile = $("#yourid");

inputfile.on("change click", function(ev){
    if (ev.originalEvent != null){
        console.log("OK clicked");
    }
    document.body.onfocus = function(){
        document.body.onfocus = null;
        setTimeout(function(){
            if (inputfile.val().length === 0) console.log("Cancel clicked");
        }, 1000);
    };
});
superdario128
quelle
Wenn Sie auf die Seite klicken ... "Abgebrochen klicken" ... = | (Getestet mit Chrome)
Eduardo Lucio
5

Hören Sie sich auch das Klickereignis an.

Nach Shiboes Beispiel ist hier ein jQuery-Beispiel:

var godzilla = $('#godzilla');
var godzillaBtn = $('#godzilla-btn');

godzillaBtn.on('click', function(){
    godzilla.trigger('click');
});

godzilla.on('change click', function(){

    if (godzilla.val() != '') {
        $('#state').html('You have chosen a Mech!');    
    } else {
        $('#state').html('Choose your Mech!');
    }

});

Sie können es hier in Aktion sehen: http://jsfiddle.net/T3Vwz

AEQ
quelle
1
Ich habe auf Chrome 51 getestet, es funktioniert nicht, wenn Sie zum ersten Mal Dateien auswählen. Die Lösung besteht darin, eine Verzögerung hinzuzufügen: jsfiddle.net/7jfbmunh
Benoit Blanchon
Ihre Geige hat bei mir nicht funktioniert - mit Firefox 58.0.2
Barrypicker
4

Sie können den Abbruch abfangen, wenn Sie dieselbe Datei wie zuvor auswählen und auf Abbrechen klicken: in diesem Fall.

Sie können es so machen:

<input type="file" id="myinputfile"/>
<script>
document.getElementById('myinputfile').addEventListener('change', myMethod, false);
function myMethod(evt) {
  var files = evt.target.files; 
  f= files[0];
  if (f==undefined) {
     // the user has clicked on cancel
  }
  else if (f.name.match(".*\.jpg")|| f.name.match(".*\.png")) {
     //.... the user has choosen an image file
     var reader = new FileReader();
     reader.onload = function(evt) { 
        try {
        myimage.src=evt.target.result;
            ...
         } catch (err) {
            ...
         }
     };
  }     
  reader.readAsDataURL(f);          
</script>
Liebe
quelle
1
Thnkx @loveJs dieser Beitrag hat mir wirklich geholfen.
VPK
4
Nicht genau, wenn der Benutzer dieselbe Datei auswählt, ist dies kein Abbruch = (
Tiago Peres França
13
onchange wird nur ausgelöst, wenn eine Änderung vorgenommen wurde. Wenn die Datei dieselbe wie die vorherige ist, wird der Onchange-Listener nicht ausgelöst.
Shane
1
Sie können die Eingabeauswahl (input.value = '') löschen, nachdem Sie die erste Änderung erkannt haben, sodass die zweite Änderung auch dann ausgelöst wird, wenn der Benutzer dieselbe Datei erneut auswählt.
Chris
1
@CodeGems Es ist erlaubt, den input.value programmgesteuert auf eine leere Zeichenfolge zu setzen. Sie haben jedoch Recht, dass das Festlegen eines anderen Werts nicht zulässig ist.
Chris
4

Am einfachsten ist es, zu überprüfen, ob sich Dateien im temporären Speicher befinden. Wenn Sie das Änderungsereignis jedes Mal erhalten möchten, wenn der Benutzer auf die Dateieingabe klickt, können Sie es auslösen.

var yourFileInput = $("#yourFileInput");

yourFileInput.on('mouseup', function() {
    $(this).trigger("change");
}).on('change', function() {
    if (this.files.length) {
        //User chose a picture
    } else {
        //User clicked cancel
    }
});
Krzysztof Janiszewski
quelle
2

Shiboes Lösung wäre gut, wenn sie mit einem mobilen Webkit funktionieren würde, aber nicht. Was ich mir einfallen lassen kann, ist, einem dom-Objekt zum Zeitpunkt des Öffnens des Dateieingabefensters einen Mausbewegungsereignis-Listener hinzuzufügen, wie folgt:

 $('.upload-progress').mousemove(function() {
        checkForFiles(this);
      });
      checkForFiles = function(me) {
        var filefield = $('#myfileinput');
        var files = filefield.get(0).files;
        if (files == undefined || files[0] == undefined) $(me).remove(); // user cancelled the upload
      };

Das Mousemove-Ereignis wird von der Seite blockiert, während der Dateidialog geöffnet ist. Wenn es geschlossen ist, wird überprüft, ob Dateien in der Dateieingabe vorhanden sind. In meinem Fall möchte ich, dass ein Aktivitätsindikator die Dinge blockiert, bis die Datei hochgeladen wird. Daher möchte ich meinen Indikator nur beim Abbrechen entfernen.

Dies lässt sich jedoch nicht für Mobilgeräte lösen, da keine Maus zum Bewegen vorhanden ist. Meine Lösung dort ist weniger als perfekt, aber ich denke, es ist gut genug.

       $('.upload-progress').bind('touchstart', function() {
        checkForFiles(this);
      });

Jetzt warten wir auf eine Berührung auf dem Bildschirm, um die gleiche Dateiprüfung durchzuführen. Ich bin ziemlich sicher, dass der Finger des Benutzers nach dem Abbrechen und Deaktivieren dieser Aktivitätsanzeige ziemlich schnell auf dem Bildschirm angezeigt wird.

Man könnte auch einfach den Aktivitätsindikator zum Änderungsereignis für die Dateieingabe hinzufügen, aber auf Mobilgeräten gibt es oft einige Sekunden Verzögerung zwischen der Auswahl des Bildes und dem Auslösen des Änderungsereignisses, so dass die UX für den Aktivitätsindikator viel besser ist Beginn des Prozesses.

Lösegeldweber
quelle
2

Ich fand dieses Attribut, das bisher einfachste.

if ($('#selectedFile')[0].files.length > 1)
{
   // Clicked on 'open' with file
} else {
   // Clicked on 'cancel'
}

Hier selectedFileist ein input type=file.

Israel
quelle
Dies ist eine gute Lösung für mich, außer dass es> = 1 sein sollte
Bron Thulke
2

Ich weiß, dass dies eine sehr alte Frage ist, aber nur für den Fall, dass sie jemandem hilft, stellte ich bei der Verwendung des Ereignisses onmousemove zum Erkennen des Abbruchs fest, dass es notwendig war, in kurzer Zeit zwei oder mehr solcher Ereignisse zu testen. Dies lag daran, dass der Browser (Chrome 65) jedes Mal, wenn der Cursor aus dem Dialogfenster für die Auswahldatei und wieder aus dem Hauptfenster heraus und wieder hinein bewegt wird, einzelne Onmousemove-Ereignisse generiert. Ein einfacher Zähler für Mausbewegungsereignisse In Verbindung mit einer kurzen Zeitüberschreitung, um den Zähler auf Null zurückzusetzen, war dies ein Vergnügen.

Steve Brooker
quelle
1
Der erste Absatz ist eine gute Antwort, obwohl er zur besseren Lesbarkeit in mehrere geteilt werden könnte. Diese beiden "SOAPBOX" -Linien grenzen jedoch an eine Nichtantwort, da Fragen nicht zu den Antworten gehören. Können Sie Ihre Antwort ein wenig umformulieren / umformulieren? Danke dir.
Filnor
1

In meinem Fall musste ich die Schaltfläche "Senden" ausblenden, während Benutzer Bilder auswählten.

Das komme ich auf:

$(document).on('click', '#image-field', function(e) {
  $('.submit-button').prop('disabled', true)
})
$(document).on('focus', '#image-field'), function(e) {
  $('.submit-button').prop('disabled', false)
})

#image-fieldist meine Dateiauswahl. Wenn jemand darauf klickt, deaktiviere ich die Schaltfläche zum Senden von Formularen. Der Punkt ist, wenn der Dateidialog geschlossen wird - egal, #image-fieldob sie eine Datei auswählen oder abbrechen -, den Fokus wieder erhalten hat, also höre ich mir dieses Ereignis an.

AKTUALISIEREN

Ich fand, dass dies bei Safari und Poltergeist / Phantomjs nicht funktioniert. Berücksichtigen Sie diese Informationen, wenn Sie sie implementieren möchten.

bonyiii
quelle
1

Durch die Kombination der Lösungen von Shiboe und alx habe ich den zuverlässigsten Code:

var selector = $('<input/>')
   .attr({ /* just for example, use your own attributes */
      "id": "FilesSelector",
      "name": "File",
      "type": "file",
      "contentEditable": "false" /* if you "click" on input via label, this prevents IE7-8 from just setting caret into file input's text filed*/
   })
   .on("click.filesSelector", function () {
      /* do some magic here, e.g. invoke callback for selection begin */
      var cancelled = false; /* need this because .one calls handler once for each event type */
      setTimeout(function () {
         $(document).one("mousemove.filesSelector focusin.filesSelector", function () {
            /* namespace is optional */
            if (selector.val().length === 0 && !cancelled) {
               cancelled = true; /* prevent double cancel */
               /* that's the point of cancel,   */
            }
         });                    
      }, 1); /* 1 is enough as we just need to delay until first available tick */
   })
   .on("change.filesSelector", function () {
      /* do some magic here, e.g. invoke callback for successful selection */
   })
   .appendTo(yourHolder).end(); /* just for example */

Im Allgemeinen reicht das Mausbewegungsereignis aus, aber falls der Benutzer einen Klick gemacht hat und dann:

  • Der Dialog zum Öffnen der Datei wurde mit der Escape-Taste abgebrochen (ohne die Maus zu bewegen). Mit einem weiteren genauen Klick wurde der Dialog zum Öffnen der Datei erneut geöffnet.
  • Der Fokus wurde auf eine andere Anwendung umgeschaltet, als zum Dialogfeld zum Öffnen von Browserdateien zurückgekehrt und geschlossen wurde. Anschließend wurde die Eingabetaste oder die Leertaste erneut geöffnet.

... wir bekommen kein Mausbewegungsereignis, daher kein Rückruf abbrechen. Wenn der Benutzer den zweiten Dialog abbricht und eine Maus bewegt, werden zwei Rückrufe abgebrochen. Glücklicherweise sprudelt in beiden Fällen ein spezielles jQuery focusIn-Ereignis in das Dokument, um solche Situationen zu vermeiden. Die einzige Einschränkung ist, wenn man das focusIn-Ereignis blockiert.

KGA
quelle
Ich habe das mousemoveEreignis documentbeim Auswählen von Dateien im Dialogfeld "Betriebssystem" in Chrome 56.0.2924.87 unter Ubuntu 16.10 festgestellt. Kein Problem, wenn Sie die Maus nicht bewegen oder nur die Tastatur zur Auswahl der Datei verwenden. Ich hatte zu ersetzen mousemovedurch , keydownum die so früh wie möglich aufheben zu erkennen, aber nicht „zu früh“, wenn der Dialog war noch offen.
Ferdinand Prantl
1

Ich sehe, dass meine Antwort ziemlich veraltet wäre, aber trotzdem. Ich hatte das gleiche Problem. Hier ist meine Lösung. Der nützlichste Code war der von KGA. Aber es funktioniert nicht ganz und ist ein bisschen kompliziert. Aber ich habe es vereinfacht.

Der Hauptstörer war auch die Tatsache, dass das Änderungsereignis nicht sofort nach dem Fokussieren eintritt, sodass wir einige Zeit warten müssen.

"#appendfile" - welcher Benutzer klickt, um eine neue Datei anzuhängen. Hrefs erhalten Fokusereignisse.

$("#appendfile").one("focusin", function () {
    // no matter - user uploaded file or canceled,
    // appendfile gets focus
    // change doesn't come instantly after focus, so we have to wait for some time
    // wrapper represents an element where a new file input is placed into
    setTimeout(function(){
        if (wrapper.find("input.fileinput").val() != "") {
            // user has uploaded some file
            // add your logic for new file here
        }
        else {
            // user canceled file upload
            // you have to remove a fileinput element from DOM
        }
    }, 900);
});
Oleksandr Khryplyvenko
quelle
1

Sie können dies nur unter bestimmten Umständen feststellen. Insbesondere in Chrome löscht Chrome die Datei und löst das Ereignis onChange aus, wenn zuvor eine Datei ausgewählt wurde und dann auf das Dateidialogfeld geklickt und auf Abbrechen geklickt wird.

https://code.google.com/p/chromium/issues/detail?id=2508

In diesem Szenario können Sie dies erkennen, indem Sie das Ereignis onChange behandeln und die Eigenschaft files überprüfen .

Kunal
quelle
1

Folgendes scheint für mich zu funktionieren (auf Desktop, Windows):

var openFile = function (mimeType, fileExtension) {
    var defer = $q.defer();
    var uploadInput = document.createElement("input");
    uploadInput.type = 'file';
    uploadInput.accept = '.' + fileExtension + ',' + mimeType;

    var hasActivated = false;

    var hasChangedBeenCalled = false;
    var hasFocusBeenCalled = false;
    var focusCallback = function () {
        if (hasActivated) {
            hasFocusBeenCalled = true;
            document.removeEventListener('focus', focusCallback, true);
            setTimeout(function () {
                if (!hasChangedBeenCalled) {
                    uploadInput.removeEventListener('change', changedCallback, true);
                    defer.resolve(null);
                }
            }, 300);
        }
    };

    var changedCallback = function () {
        uploadInput.removeEventListener('change', changedCallback, true);
        if (!hasFocusBeenCalled) {
            document.removeEventListener('focus', focusCallback, true);
        }
        hasChangedBeenCalled = true;
        if (uploadInput.files.length === 1) {
            //File picked
            var reader = new FileReader();
            reader.onload = function (e) {
                defer.resolve(e.target.result);
            };
            reader.readAsText(uploadInput.files[0]);
        }
        else {
            defer.resolve(null);
        }
    };
    document.addEventListener('focus', focusCallback, true); //Detect cancel
    uploadInput.addEventListener('change', changedCallback, true); //Detect when a file is picked
    uploadInput.click();
    hasActivated = true;
    return defer.promise;
}

Dies verwendet zwar anglejs $ q, aber Sie sollten es bei Bedarf durch ein anderes Versprechen-Framework ersetzen können.

Getestet auf IE11, Edge, Chrome, Firefox, aber es scheint nicht auf Chrome auf einem Android-Tablet zu funktionieren, da das Focus-Ereignis nicht ausgelöst wird.

Peter
quelle
1

Das fileFeld vom Typ "reagiert frustrierend nicht auf viele Ereignisse (Unschärfe wäre sehr schön). Ich sehe viele Leute, die changeorientierte Lösungen vorschlagen, und sie werden herabgestimmt.

changefunktioniert, aber es hat einen großen Fehler (im Vergleich zu dem, was wir wollen ).

Wenn Sie eine Seite mit einem Dateifeld neu laden, öffnen Sie das Feld und klicken Sie auf Abbrechen. Frustrierend ändert sich nichts .

Was ich gewählt habe, ist das Laden in einem geschlossenen Zustand.

  • Der nächste Teil des Formulars a ist section#after-imagein meinem Fall nicht sichtbar. Bei meinen file fieldÄnderungen wird eine Upload-Schaltfläche angezeigt. Nach erfolgreichem Upload section#after-imagewird angezeigt.
  • Wenn der Benutzer lädt, den Dateidialog öffnet und dann abbricht, wird der Upload-Button nie angezeigt.
  • Wenn der Benutzer eine Datei auswählt, wird die Schaltfläche zum Hochladen angezeigt. Wenn sie dann den Dialog öffnen und abbrechen, wird das changeEreignis durch diesen Abbruch ausgelöst, und dort kann (und kann) ich meine Upload-Schaltfläche wieder ausblenden, bis eine richtige Datei ausgewählt ist.

Ich hatte das Glück, dass dieser geschlossene Zustand bereits das Design meiner Form war. Sie müssen nicht denselben Stil verwenden, sondern lediglich die Schaltfläche zum Hochladen zunächst ausblenden und beim Ändern ein ausgeblendetes Feld oder eine Javascript-Variable auf etwas setzen, das Sie beim Senden überwachen können.

Ich habe versucht, den Wert von Dateien [0] zu ändern, bevor mit dem Feld interagiert wurde. Dies hat nichts in Bezug auf den Wechsel bewirkt.

Also ja, changefunktioniert, mindestens so gut wie wir es bekommen werden. Das Dateifeld ist aus offensichtlichen Gründen gesichert, aber zur Frustration gut gemeinter Entwickler.

Es passt nicht zu meinem Zweck, aber Sie können möglicherweise onclickeine Warnmeldung laden (keine alert(), da dies die Seitenverarbeitung blockiert) und sie ausblenden, wenn eine Änderung ausgelöst wird und files [0] null ist. Wenn keine Änderung ausgelöst wird, bleibt das div in seinem Zustand.

Normaler Joe
quelle
0

Es gibt eine hackige Möglichkeit, dies zu tun (Rückrufe hinzufügen oder eine verzögerte / versprochene Implementierung anstelle von alert()Aufrufen auflösen ):

var result = null;

$('<input type="file" />')
    .on('change', function () {
        result = this.files[0];
        alert('selected!');
    })
    .click();

setTimeout(function () {
    $(document).one('mousemove', function () {
        if (!result) {
            alert('cancelled');
        }
    });
}, 1000);

So funktioniert es: Während der Dateiauswahldialog geöffnet ist, empfängt das Dokument keine Mauszeigerereignisse. Es gibt eine Verzögerung von 1000 ms, damit der Dialog tatsächlich angezeigt wird und das Browserfenster blockiert wird. Eingecheckt in Chrome und Firefox (nur Windows).

Dies ist natürlich keine zuverlässige Methode, um abgebrochene Dialoge zu erkennen. Dies könnte jedoch das Verhalten der Benutzeroberfläche für Sie verbessern.

alx
quelle
Ein großer Nachteil ist, dass Telefone und Tablets normalerweise keine Mäuse verwenden!
Peter
0

Hier ist meine Lösung mit dem Dateieingabefokus (ohne Timer)

var fileInputSelectionInitiated = false;

function fileInputAnimationStart() {
    fileInputSelectionInitiated = true;
    if (!$("#image-selector-area-icon").hasClass("fa-spin"))
        $("#image-selector-area-icon").addClass("fa-spin");
    if (!$("#image-selector-button-icon").hasClass("fa-spin"))
        $("#image-selector-button-icon").addClass("fa-spin");
}

function fileInputAnimationStop() {
    fileInputSelectionInitiated = false;
    if ($("#image-selector-area-icon").hasClass("fa-spin"))
        $("#image-selector-area-icon").removeClass("fa-spin");
    if ($("#image-selector-button-icon").hasClass("fa-spin"))
        $("#image-selector-button-icon").removeClass("fa-spin");
}

$("#image-selector-area-wrapper").click(function (e) {
    $("#fileinput").focus();
    $("#fileinput").click();
});

$("#preview-image-wrapper").click(function (e) {
    $("#fileinput").focus();
    $("#fileinput").click();
});

$("#fileinput").click(function (e) {
    fileInputAnimationStart();
});

$("#fileinput").focus(function (e) {
    fileInputAnimationStop();
});

$("#fileinput").change(function(e) {
    // ...
}

Yovav
quelle
Das Ausführen Ihres Snippets gibt mirError: { "message": "Uncaught SyntaxError: missing ) after argument list", "filename": "https://stacksnippets.net/js", "lineno": 51, "colno": 1 }
connexo
0

Dies ist bestenfalls hackig, aber hier ist ein funktionierendes Beispiel meiner Lösung, um festzustellen, ob ein Benutzer eine Datei hochgeladen hat oder nicht, und um ihm nur dann zu erlauben, fortzufahren, wenn er eine Datei hochgeladen hat.

Grundsätzlich verstecken die Continue, Save, Proceedoder was auch immer Ihre Taste ist. Dann greifen Sie im JavaScript auf den Dateinamen zu. Wenn der Dateiname keinen Wert hat, wird die ContinueSchaltfläche nicht angezeigt. Wenn es einen Wert hat, zeigen Sie die Schaltfläche. Dies funktioniert auch, wenn sie zuerst eine Datei hochladen und dann versuchen, eine andere Datei hochzuladen und auf Abbrechen klicken.

Hier ist der Code.

HTML:

<div class="container">
<div class="row">
    <input class="file-input" type="file" accept="image/*" name="fileUpload" id="fileUpload" capture="camera">
    <label for="fileUpload" id="file-upload-btn">Capture or Upload Photo</label>
</div>
<div class="row padding-top-two-em">
    <input class="btn btn-success hidden" id="accept-btn" type="submit" value="Accept & Continue"/>
    <button class="btn btn-danger">Back</button>
</div></div>

JavaScript:

$('#fileUpload').change(function () {
    var fileName = $('#fileUpload').val();
    if (fileName != "") {
        $('#file-upload-btn').html(fileName);
        $('#accept-btn').removeClass('hidden').addClass('show');
    } else {
        $('#file-upload-btn').html("Upload File");
        $('#accept-btn').addClass('hidden');
    }
});

CSS:

.file-input {
    width: 0.1px;
    height: 0.1px;
    opacity: 0;
    overflow: hidden;
    position: absolute;
    z-index: -1; 
}

.file-input + label {
    font-size: 1.25em;
    font-weight: normal;
    color: white;
    background-color: blue;
    display: inline-block;
    padding: 5px;
}

.file-input:focus + label,
.file-input + label:hover {
    background-color: red;
}

.file-input + label {
    cursor: pointer;
}

.file-input + label * {
    pointer-events: none;
}

Für das CSS bedeutet dies viel, die Website und die Schaltfläche für alle zugänglich zu machen. Gestalten Sie Ihren Button nach Ihren Wünschen.

maxshuty
quelle
0

Nun, das beantwortet Ihre Frage nicht genau. Ich gehe davon aus, dass Sie ein Szenario haben, in dem Sie eine Dateieingabe hinzufügen und die Dateiauswahl aufrufen. Wenn der Benutzer auf Abbrechen klickt, entfernen Sie einfach die Eingabe.

Wenn dies der Fall ist, dann: Warum leere Dateieingaben hinzufügen?

Erstellen Sie die Datei im laufenden Betrieb, fügen Sie sie jedoch nur dann zum DOM hinzu, wenn sie ausgefüllt ist.

    var fileInput = $("<input type='file' name='files' style='display: none' />");
    fileInput.bind("change", function() {
        if (fileInput.val() !== null) {
            // if has value add it to DOM
            $("#files").append(fileInput);
        }
    }).click();

Also erstelle ich hier <input type = "file" /> im laufenden Betrieb, binde an das Änderungsereignis und rufe dann sofort click auf. Bei Änderung wird nur ausgelöst, wenn der Benutzer eine Datei auswählt und auf OK drückt. Andernfalls werden keine Eingaben zum DOM hinzugefügt und daher nicht gesendet.

Arbeitsbeispiel hier: https://jsfiddle.net/69g0Lxno/3/

Alexey
quelle
0

// Verwenden Sie Hover anstelle von Unschärfe

var fileInput = $("#fileInput");

if (fileInput.is(":hover") { 

    //open
} else {

}
jsil
quelle
0

Wenn Sie JQuery bereits benötigen, erledigt diese Lösung möglicherweise die Arbeit (dies ist genau der Code, den ich in meinem Fall tatsächlich benötigt habe, obwohl die Verwendung eines Versprechens nur dazu dient, den Code zu zwingen, zu warten, bis die Dateiauswahl aufgelöst wurde):

await new Promise(resolve => {
    const input = $("<input type='file'/>");
    input.on('change', function() {
        resolve($(this).val());
    });
    $('body').one('focus', '*', e => {
        resolve(null);
        e.stopPropagation();
    });
    input.click();

});

user2397355
quelle
0

In diesem Thread werden mehrere Lösungen vorgeschlagen, und diese Schwierigkeit, zu erkennen, wann der Benutzer auf die Schaltfläche "Abbrechen" im Dateiauswahlfeld klickt, ist ein Problem, das viele Menschen betrifft.

Tatsache ist, dass es keine 100% zuverlässige Methode gibt, um festzustellen, ob der Benutzer auf die Schaltfläche "Abbrechen" im Dateiauswahlfeld geklickt hat . Es gibt jedoch Möglichkeiten, zuverlässig zu erkennen, ob der Benutzer der Eingabedatei eine Datei hinzugefügt hat . Das ist also die Grundstrategie dieser Antwort!

Ich habe beschlossen, diese Antwort hinzuzufügen, da die anderen Antworten anscheinend in den meisten Browsern nicht funktionieren oder auf Mobilgeräten garantiert sind.

Kurz gesagt basiert der Code auf 3 Punkten:

  1. Die Eingabedatei wird anfänglich dynamisch im "Speicher" in js erstellt (wir fügen sie derzeit nicht zum "HTML" hinzu).
  2. Nach dem Hinzufügen der Datei wird die Eingabedatei zum HTML-Code hinzugefügt, andernfalls tritt nichts auf.
  3. Das Entfernen der Datei erfolgt durch Entfernen der Eingabedatei aus dem HTML-Code durch ein bestimmtes Ereignis. Dies bedeutet, dass das "Bearbeiten" / "Ändern" der Datei durch Entfernen der alten Eingabedatei und Erstellen einer neuen erfolgt.

Zum besseren Verständnis lesen Sie den folgenden Code und die Hinweise.

[...]
<button type="button" onclick="addIptFl();">ADD INPUT FILE!</button>
<span id="ipt_fl_parent"></span>
[...]
function dynIptFl(jqElInst, funcsObj) {
    if (typeof funcsObj === "undefined" || funcsObj === "") {
        funcsObj = {};
    }
    if (funcsObj.hasOwnProperty("before")) {
        if (!funcsObj["before"].hasOwnProperty("args")) {
            funcsObj["before"]["args"] = [];
        }
        funcsObj["before"]["func"].apply(this, funcsObj["before"]["args"]);
    }
    var jqElInstFl = jqElInst.find("input[type=file]");

    // NOTE: Open the file selection box via js. By Questor
    jqElInstFl.trigger("click");

    // NOTE: This event is triggered if the user selects a file. By Questor
    jqElInstFl.on("change", {funcsObj: funcsObj}, function(e) {

        // NOTE: With the strategy below we avoid problems with other unwanted events
        // that may be associated with the DOM element. By Questor
        e.preventDefault();

        var funcsObj = e.data.funcsObj;
        if (funcsObj.hasOwnProperty("after")) {
            if (!funcsObj["after"].hasOwnProperty("args")) {
                funcsObj["after"]["args"] = [];
            }
            funcsObj["after"]["func"].apply(this, funcsObj["after"]["args"]);
        }
    });

}

function remIptFl() {

    // NOTE: Remove the input file. By Questor
    $("#ipt_fl_parent").empty();

}

function addIptFl() {

    function addBefore(someArgs0, someArgs1) {
    // NOTE: All the logic here happens just before the file selection box opens.
    // By Questor

        // SOME CODE HERE!

    }

    function addAfter(someArgs0, someArgs1) {
    // NOTE: All the logic here happens only if the user adds a file. By Questor

        // SOME CODE HERE!

        $("#ipt_fl_parent").prepend(jqElInst);

    }

    // NOTE: The input file is hidden as all manipulation must be done via js.
    // By Questor
    var jqElInst = $('\
<span>\
    <button type="button" onclick="remIptFl();">REMOVE INPUT FILE!</button>\
    <input type="file" name="input_fl_nm" style="display: block;">\
</span>\
');

    var funcsObj = {
        before: {
            func: addBefore,
            args: [someArgs0, someArgs1]
        },
        after: {
            func: addAfter,

            // NOTE: The instance with the input file ("jqElInst") could be passed
            // here instead of using the context of the "addIptFl()" function. That
            // way "addBefore()" and "addAfter()" will not need to be inside "addIptFl()",
            // for example. By Questor
            args: [someArgs0, someArgs1]

        }
    };
    dynIptFl(jqElInst, funcsObj);

}

Vielen Dank! = D.

Eduardo Lucio
quelle
0

Wir haben in Winkel wie unten erreicht.

    1. Bindungsklickereignis für Eingabetypdatei.
      1. Fügen Sie das Fokusereignis mit dem Fenster hinzu und fügen Sie eine Bedingung hinzu, wenn uploadPanel true ist, und zeigen Sie dann die Konsole an.
      2. Wenn Sie auf eine Eingabetypdatei klicken, ist der boolesche uploadPanel-Wert true. und Dialogfeld werden angezeigt.
      3. Wenn Sie auf die Schaltfläche Abbrechen ODER Esc klicken, werden die Dialogbox-Apotheke und die Konsole angezeigt.

HTML

 <input type="file" formControlName="FileUpload" click)="handleFileInput($event.target.files)" />
          />

TS

this.uploadPanel = false;
handleFileInput(files: FileList) {
    this.fileToUpload = files.item(0);
    console.log("ggg" + files);
    this.uploadPanel = true;
  }



@HostListener("window:focus", ["$event"])
  onFocus(event: FocusEvent): void {
    if (this.uploadPanel == true) {
        console.log("cancel clicked")
        this.addSlot
        .get("FileUpload")
        .setValidators([
          Validators.required,
          FileValidator.validate,
          requiredFileType("png")
        ]);
      this.addSlot.get("FileUpload").updateValueAndValidity();
    }
  }
Mayank plötzlich
quelle
0

Fügen Sie einfach "Listener" zu Ihrer Eingabe hinzu, deren Typ Datei ist. dh

<input type="file" id="file_to_upload" name="file_to_upload" />

Ich habe jQuery verwendet und natürlich kann jeder Valina JS verwenden (gemäß den Anforderungen).

$("#file_to_upload").change(function() {

            if (this.files.length) {

            alert('file choosen');

            } else {

            alert('file NOT choosen');

            }

    });
Naveed Ali
quelle
.change()wird nicht zuverlässig aufgerufen, wenn der Benutzer in der Dateiauswahl auf "Abbrechen" klickt.
Ben Wheeler
@benWheeler, ich habe es sowohl auf Chrome als auch auf Firefox überprüft und es hat funktioniert, aber nicht auf anderen Browsern getestet.
Naveed Ali
0
    enter code here
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello</h1>
    <div id="cancel01">
      <button>Cancel</button>
    </div>

    <div id="cancel02">
      <button>Cancel</button>
    </div>

    <div id="cancel03">
      <button>Cancel</button>
    </div>

    <form>
      <input type="file" name="name" placeholder="Name" />
    </form>

    <script>
      const nameInput = document.querySelector('input[type="file"]');

      /******
       *The below code if for How to detect when cancel is clicked on file input
       ******/
      nameInput.addEventListener('keydown', e => {
        /******
         *If the cancel button is clicked,then you should change the input file value to empty
         ******/

        if (e.key == 'Backspace' || e.code == 'Backspace' || e.keyCode == 8) {
          console.log(e);

          /******
           *The below code will delete the file path
           ******/
          nameInput.value = '';
        }
      });
    </script>
  </body>
</html>
Emmanuel Onah
quelle
Nur-Code-Antworten gelten als minderwertig: Stellen Sie sicher, dass Sie erklären, was Ihr Code tut und wie er das Problem löst. Es wird sowohl dem Fragesteller als auch zukünftigen Lesern helfen, wenn Sie Ihrem Beitrag weitere Informationen hinzufügen können. Siehe Erklären vollständig
codebasierter
0

Lösung für die Dateiauswahl mit versteckter Eingabe

Hinweis: Dieser Code erkennt keine Stornierung. Er bietet eine Möglichkeit, die Notwendigkeit zu umgehen, ihn in einem häufigen Fall zu erkennen, in dem Personen versuchen, ihn zu erkennen.

Ich bin hierher gekommen, als ich nach einer Lösung für das Hochladen von Dateien mithilfe einer versteckten Eingabe gesucht habe. Ich glaube, dass dies der häufigste Grund ist, nach einer Möglichkeit zu suchen, die Stornierung der Dateieingabe zu erkennen (Dialogfeld "Datei öffnen" -> Wenn eine Datei ausgewählt wurde, führen Sie einige aus Code, sonst nichts tun), hier ist meine Lösung:

var fileSelectorResolve;
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');

fileSelector.addEventListener('input', function(){
   fileSelectorResolve(this.files[0]);
   fileSelectorResolve = null;
   fileSelector.value = '';
});

function selectFile(){
   if(fileSelectorResolve){
      fileSelectorResolve();
      fileSelectorResolve = null;
   }
   return new Promise(function(resolve){
      fileSelectorResolve = resolve;
      fileSelector.dispatchEvent(new MouseEvent('click'));
   });
}

Anwendungsbeispiel:

Beachten Sie, dass, wenn keine Datei ausgewählt wurde, die erste Zeile nur einmal zurückgegeben selectFile()wird und erneut aufgerufen wird (oder wenn Sie fileSelectorResolve()von einer anderen Stelle aus angerufen haben ).

async function logFileName(){
   const file = await selectFile();
   if(!file) return;
   console.log(file.name);
}

Ein anderes Beispiel:

async function uploadFile(){
   const file = await selectFile();
   if(!file) return;

   // ... make an ajax call here to upload the file ...
}
Kartoffel
quelle
In Chrome 83.0 erhalte ich keinen Rückruf für das Eingabeereignis, wenn der Benutzer abbricht, und auch nicht beim zweiten Versuch
Soylent Graham,
1
@SoylentGraham Ja, da dieser Code keine Stornierung erkennt, bietet er eine Möglichkeit, die Notwendigkeit zu umgehen, ihn in einem häufigen Fall zu erkennen, in dem Personen versuchen, ihn zu erkennen. Da mir das nicht klar war, füge ich diesen Kommentar meiner Antwort hinzu.
Kartoffel
Mein schlechtes Ich denke, ich habe Ihre Antwort falsch verstanden als "es sagt Ihnen, dass Benutzer beim 2. Versuch abgebrochen wurde"
Soylent Graham
-1

Sie können einen Listener für jquery change im Eingabefeld erstellen und anhand des Werts des Felds erkennen, dass der Benutzer das Upload-Fenster abbricht oder schließt.

Hier ist ein Beispiel:

//when upload button change
$('#upload_btn').change(function(){
    //get uploaded file
    var file = this.files[0];

    //if user choosed a file
    if(file){
        //upload file or perform your desired functiuonality
    }else{
        //user click cancel or close the upload window
    }
});
Mohamed Hana
quelle
Keine Ahnung, warum dies abgelehnt wird - das habe ich gesucht. Danke dir! 🙂
user1274820