Ich habe Probleme, Dokumentation oder Beispiele für die Implementierung einer Upload-Fortschrittsanzeige mithilfe von Fetch zu finden .
Dies ist die einzige Referenz, die ich bisher gefunden habe und die besagt:
Fortschrittsereignisse sind eine übergeordnete Funktion, die vorerst nicht abgerufen werden kann. Sie können Ihre eigenen erstellen, indem Sie sich den
Content-Length
Header ansehen und einen Pass-Through-Stream verwenden, um die empfangenen Bytes zu überwachen.Dies bedeutet, dass Sie Antworten explizit ohne eine
Content-Length
andere behandeln können. Und selbst wennContent-Length
es da ist, kann es natürlich eine Lüge sein. Mit Streams können Sie mit diesen Lügen umgehen, wie Sie wollen.
Wie würde ich "einen Pass-Through-Stream zur Überwachung der gesendeten Bytes" schreiben? Wenn es einen Unterschied macht, versuche ich dies, um das Hochladen von Bildern vom Browser auf Cloudinary zu ermöglichen .
HINWEIS : Die Cloudinary JS-Bibliothek interessiert mich nicht , da sie von jQuery abhängt und meine App nicht. Ich interessiere mich nur für die Stream-Verarbeitung, die dazu mit nativem Javascript und Githubs Polyfill erforderlich ist .fetch
quelle
Antworten:
Streams landen allmählich auf der Webplattform ( https://jakearchibald.com/2016/streams-ftw/ ), aber es ist noch früh.
Bald können Sie einen Stream als Hauptteil einer Anfrage bereitstellen, aber die offene Frage ist, ob sich der Verbrauch dieses Streams auf hochgeladene Bytes bezieht.
Bestimmte Weiterleitungen können dazu führen, dass Daten erneut an den neuen Speicherort übertragen werden, Streams können jedoch nicht "neu gestartet" werden. Wir können dies beheben, indem wir den Body in einen Rückruf verwandeln, der mehrmals aufgerufen werden kann. Wir müssen jedoch sicherstellen, dass das Offenlegen der Anzahl der Weiterleitungen kein Sicherheitsleck darstellt, da dies das erste Mal auf der Plattform JS sein könnte erkenne das.
Einige fragen sich, ob es überhaupt Sinn macht, den Stream-Verbrauch mit hochgeladenen Bytes zu verknüpfen.
Lange Rede, kurzer Sinn: Dies ist noch nicht möglich, aber in Zukunft wird dies entweder durch Streams oder durch eine Art Rückruf auf höherer Ebene erledigt
fetch()
.quelle
Meine Lösung besteht darin, Axios zu verwenden , was dies ziemlich gut unterstützt:
Ich habe ein Beispiel dafür, wie man dies auf Github reagiert .
quelle
axios
Verwendungfetch
oderXMLHttpRequest
unter der Motorhaube?axios
es nichtfetch
unter der Haube verwendet wird und keine solche Unterstützung hat. Ich schreibe es jetzt buchstäblich für sie so.Ich denke nicht, dass es möglich ist. Der Entwurf besagt:
(alte Antwort):
Das erste Beispiel im Kapitel Fetch API gibt einen Einblick in die Vorgehensweise :
Abgesehen von der Verwendung des
Promise
Konstruktor-Antimusters können Sie sehen, dassresponse.body
es sich um einen Stream handelt, aus dem Sie mit einem Reader Byte für Byte lesen können, und Sie können für jeden von ihnen ein Ereignis auslösen oder tun, was Sie möchten (z. B. den Fortschritt protokollieren).Die Streams-Spezifikation scheint jedoch noch nicht ganz fertig zu sein, und ich habe keine Ahnung, ob dies bereits in einer Abrufimplementierung funktioniert.
quelle
fetch
. Ich interessiere mich für Fortschrittsanzeigen zum Hochladen einer Datei.Promise
Konstruktor ist nicht erforderlich.Response.body.getReader()
gibt a zurückPromise
. Siehe So lösen Sie Uncaught RangeError beim Herunterladen von jsongetReader
gibt kein Versprechen zurück. Keine Ahnung, was dies mit dem von Ihnen verlinkten Beitrag zu tun hat..getReader()
Die.read()
Methode gibt a zurückPromise
. Das wollte ich vermitteln. Der Link soll auf die Prämisse verweisen, dass, wenn der Fortschritt zum Herunterladen überprüft werden kann, der Fortschritt zum Hochladen überprüft werden kann. Stellen Sie ein Muster zusammen, das das erwartete Ergebnis in nennenswertem Maße zurückgibt. Das ist ein Fortschritt beimfetch()
Hochladen. Habe bei jsfiddle keinen Weg zuecho
einemBlob
oder einemFile
Objekt gefunden, wahrscheinlich fehlt etwas Einfaches. Testen beilocalhost
Upload-Dateien sehr schnell, ohne die Netzwerkbedingungen nachzuahmen; obwohl gerade erinnertNetwork throttling
.Update: Wie die akzeptierte Antwort sagt, ist es jetzt unmöglich. Aber der folgende Code hat unser Problem für einige Zeit gelöst. Ich sollte hinzufügen, dass wir zumindest auf eine Bibliothek umsteigen mussten, die auf XMLHttpRequest basiert.
Dank diesem Link: https://jakearchibald.com/2016/streams-ftw/
quelle
content-length
! == Körperlänge. Wenn die http-Komprimierung verwendet wird (häufig bei großen Downloads), entspricht die Inhaltslänge der Größe nach der http-Komprimierung, während die Länge der Größe nach dem Extrahieren der Datei entspricht.Da keine der Antworten das Problem löst.
Nur zur Implementierung können Sie die Upload-Geschwindigkeit mit einem kleinen Anfangsblock bekannter Größe ermitteln und die Upload-Zeit mit der Länge des Inhalts / der Upload-Geschwindigkeit berechnen. Sie können diese Zeit als Schätzung verwenden.
quelle
Eine mögliche Problemumgehung wäre, den
new Request()
Konstruktor zu verwenden und dann dasRequest.bodyUsed
Boolean
Attribut zu überprüfenum festzustellen, ob Stream ist
distributed
Geben Sie den
fetch()
Promise
von innen.then()
verketteten bis rekursiven.read()
Aufruf einesReadableStream
WannRequest.bodyUsed
gleich gleich zurücktrue
.Beachten Sie, dass der Ansatz die Bytes von nicht liest,
Request.body
wenn die Bytes zum Endpunkt gestreamt werden. Außerdem kann der Upload abgeschlossen sein, bevor eine Antwort vollständig an den Browser zurückgegeben wird.quelle
quelle
Schlüsselteil ist ReadableStream ≪ obj_response .body).
Stichprobe:
Sie können es auf einer großen Seite testen, z. B. https://html.spec.whatwg.org/ und . https://html.spec.whatwg.org/print.pdf . CtrlShiftJ und laden Sie den Code in.
(Auf Chrome getestet.)
quelle