Ich glaube, einige von Ihnen kennen bereits die Lösung zum Hochladen großer Dateien. Beim Hochladen großer Dateien verwenden wir zur Verbesserung der Upload-Effizienz im Allgemeinen die Blob.slice-Methode, um die große Datei entsprechend der angegebenen Größe zu zerschneiden, und starten dann Multithreading, um sie in Blöcken hochzuladen. Nachdem alle Blöcke erfolgreich hochgeladen wurden, benachrichtigen Sie den Server, um die Blöcke zusammenzuführen. Können wir also eine ähnliche Idee für den Download großer Dateien übernehmen? Wenn der Server den Range-Anforderungsheader unterstützt, können wir auch das Herunterladen von Blöcken mit mehreren Threads implementieren, wie in der folgenden Abbildung dargestellt: Nachdem Sie das obige Bild gelesen haben, glaube ich, dass Sie ein gewisses Verständnis für die Lösung zum Herunterladen großer Dateien haben. Als Nächstes stellen wir HTTP-Bereichsanforderungen vor. 1. HTTP-BereichsanforderungDie HTTP-Protokollbereichsanforderung ermöglicht es dem Server, nur einen Teil einer HTTP-Nachricht an den Client zu senden. Bereichsanforderungen sind beim Übertragen großer Mediendateien oder in Verbindung mit der Funktion zum Fortsetzen eines Dateidownloads nützlich. Wenn der Accept-Ranges-Header in der Antwort vorhanden ist (und sein Wert nicht „none“ ist), zeigt dies an, dass der Server Bereichsanforderungen unterstützt. In einem Range-Header können Sie mehrere Teile gleichzeitig anfordern und der Server gibt sie in Form von mehrteiligen Dateien zurück. Wenn der Server eine Bereichsantwort zurückgibt, sollte der Statuscode 206 „Partial Content“ verwendet werden. Wenn der angeforderte Bereich ungültig ist, gibt der Server den Statuscode 416 „Bereich nicht erfüllbar“ zurück, der auf einen Clientfehler hinweist. Der Server darf den Range-Header ignorieren und die gesamte Datei mit einem Statuscode von 200 zurückgeben. 1.1 BereichssyntaxBereich: <Einheit>=<Bereichsanfang>- Bereich: <Einheit>=<Bereichsanfang>-<Bereichsende> Bereich: <Einheit>=<Bereichsanfang>-<Bereichsende>, <Bereichsanfang>-<Bereichsende> Bereich: <Einheit>=<Bereichsanfang>-<Bereichsende>, <Bereichsanfang>-<Bereichsende>, <Bereichsanfang>-<Bereichsende>
Nachdem wir die Range-Syntax verstanden haben, schauen wir uns ein konkretes Anwendungsbeispiel an: 1.1.1 Einzelkategorie $ curl http://i.imgur.com/z4d4kWk.jpg -i -H "Bereich: Bytes=0-1023" 1.1.2 Mehrere Bereiche $ curl http://www.example.com -i -H "Bereich: Bytes=0-50, 100-150" So, das ist alles Wissenswerte über HTTP-Bereichsanforderungen. Kommen wir nun zur Sache und zeigen Ihnen, wie Sie große Dateien herunterladen. 2. So laden Sie große Dateien herunterDamit Sie die folgenden Inhalte besser verstehen, werfen wir einen Blick auf das gesamte Flussdiagramm: Nachdem wir den Vorgang des Herunterladens großer Dateien verstanden haben, definieren wir zunächst einige Hilfsfunktionen, die am obigen Vorgang beteiligt sind. 2.1 Hilfsfunktionen definieren2.1.1 Definieren Sie die Funktion getContentLength Wie der Name schon sagt, wird die Funktion getContentLength verwendet, um die Länge der Datei zu ermitteln. In dieser Funktion senden wir eine HEAD-Anfrage und lesen dann die Content-Length-Informationen aus dem Antwortheader, um die Inhaltslänge der Datei zu erhalten, die der aktuellen URL entspricht. Funktion getContentLength(url) { returniere neues Promise((lösen, ablehnen) => { let xhr = neue XMLHttpRequest(); xhr.open("HEAD", URL); xhr.senden(); xhr.onload = Funktion () { lösen( ~~xhr.getResponseHeader("Inhaltslänge") ); }; xhr.onerror = ablehnen; }); } 2.1.2 Definieren Sie die asyncPool-Funktion. Wie implementiert man die Parallelitätssteuerung in JavaScript? In diesem Artikel haben wir die Funktion asyncPool vorgestellt, die zur Implementierung der Parallelitätssteuerung asynchroner Aufgaben verwendet wird. Diese Funktion erhält 3 Parameter:
asynchrone Funktion asyncPool(PoolLimit, Array, IteratorFn) { const ret = []; // Alle asynchronen Aufgaben speichern const executing = []; // Die asynchronen Aufgaben speichern, die ausgeführt werden für (const item of array) { // Rufen Sie die Funktion iteratorFn auf, um eine asynchrone Aufgabe zu erstellen. const p = Promise.resolve().then(() => iteratorFn(item, array)); ret.push(p); // Neue asynchrone Aufgaben speichern // Wenn der PoolLimit-Wert kleiner oder gleich der Gesamtzahl der Aufgaben ist, führe eine Parallelitätskontrolle durch, wenn (PoolLimit <= Array.Länge) { // Wenn die Aufgabe abgeschlossen ist, entfernen Sie die abgeschlossene Aufgabe aus dem Array der ausgeführten Aufgaben const e = p.then(() => executing.splice(executing.indexOf(e), 1)); executing.push(e); // Speichere die ausgeführte asynchrone Aufgabe, wenn (executing.length >= poolLimit) { warte auf Promise.race(executing); // Warte, bis die schnellere Aufgabe abgeschlossen ist } } } gibt Promise.all(ret) zurück; } 2.1.3 Definieren Sie die Funktion getBinaryContent Funktion getBinaryContent(url, start, end, i) { returniere neues Promise((lösen, ablehnen) => { versuchen { let xhr = neue XMLHttpRequest(); xhr.open("GET", URL, wahr); xhr.setRequestHeader("range", `bytes=${start}-${end}`); // Setzt die Bereichsanforderungsinformationen im Anforderungsheader xhr.responseType = "arraybuffer"; // Setzt den Rückgabetyp auf arraybuffer xhr.onload = Funktion () { lösen({ index: i, // Index des Dateiblockpuffers: xhr.response, // Daten entsprechend der Bereichsanforderung }); }; xhr.senden(); } fangen (Fehler) { ablehnen(neuer Fehler(err)); } }); } Beachten Sie, dass ArrayBuffer-Objekte zur Darstellung allgemeiner Puffer für Rohbinärdaten mit fester Länge verwendet werden. Wir können den Inhalt von ArrayBuffer nicht direkt manipulieren, sondern über typisierte Array-Objekte oder DataView-Objekte, die die Daten im Puffer in einem bestimmten Format darstellen und diese Formate zum Lesen und Schreiben des Inhalts des Puffers verwenden. 2.1.4 Definieren Sie die Verkettungsfunktion. Da wir nicht direkt mit ArrayBuffer-Objekten arbeiten können, müssen wir die ArrayBuffer-Objekte zuerst in Uint8Array-Objekte konvertieren und dann die Verkettungsoperation durchführen. Die unten definierte Verkettungsfunktion wird zum Zusammenführen der heruntergeladenen Dateidatenblöcke verwendet. Der spezifische Code lautet wie folgt: Funktion verketten(Arrays) { wenn (!arrays.length) null zurückgibt; Lassen Sie totalLength = arrays.reduce((acc, value) => acc + value.length, 0); let Ergebnis = neues Uint8Array(Gesamtlänge); lass Länge = 0; für (let Array von Arrays) { Ergebnis.Satz(Array, Länge); Länge += Array.Länge; } Ergebnis zurückgeben; } 2.1.5 Definieren der Funktion saveAs Funktion saveAs({ Name, Puffer, MIME = "Anwendung/Oktett-Stream" }) { const blob = neuer Blob([Puffer], { Typ: MIME }); const blobUrl = URL.createObjectURL(blob); const a = document.createElement("a"); a.download = Name || Math.random(); a.href = blobUrl; ein.Klick(); URL.revokeObjectURL(blob); } In der Funktion „saveAs“ haben wir Blob- und Objekt-URL verwendet. Object URL ist ein Pseudoprotokoll, das die Verwendung von Blob- und File-Objekten als URL-Quellen für Bilder, herunterladbare Binärdatenlinks usw. ermöglicht. Im Browser verwenden wir die Methode URL.createObjectURL, um eine Objekt-URL zu erstellen. Diese Methode empfängt ein Blob-Objekt und erstellt dafür eine eindeutige URL in der Form blob:<origin>/<uuid>. Das entsprechende Beispiel sieht wie folgt aus:
Der Browser speichert intern eine URL → Blob-Zuordnung für jede über URL.createObjectURL generierte URL. Daher sind solche URLs kürzer, können aber auf den Blob zugreifen. Die generierte URL ist nur gültig, während das aktuelle Dokument geöffnet ist. OK, das ist alles zu Objekt-URLs. 2.1.6 Download-Funktion definieren Die Download-Funktion wird zum Implementieren des Download-Vorgangs verwendet und unterstützt 3 Parameter:
asynchrone Funktion Download({ URL, ChunkSize, PoolLimit = 1 }) { const contentLength = warte auf getContentLength(url); const chunks = Typ von chunkSize === "Zahl" ? Math.ceil(Inhaltslänge / chunkSize) : 1; const Ergebnisse = warte auf asyncPool( PoolLimit, [...neues Array(Chunks).Schlüssel()], (i) => { lass start = i * Blockgröße; let end = i + 1 == chunks? Inhaltslänge – 1 : (i + 1) * chunkSize – 1; returniere getBinaryContent(URL, Start, Ende, i); } ); const sortedBuffers = Ergebnisse .map((item) => neues Uint8Array(item.buffer)); returniere Verkettung (sortierte Puffer); } 2.2 Beispiel für den Download großer DateienBasierend auf der oben definierten Hilfsfunktion können wir problemlos das parallele Herunterladen großer Dateien implementieren. Der spezifische Code lautet wie folgt: Funktion multiThreadedDownload() { const url = document.querySelector("#fileUrl").value; wenn (!url || !/https?/.test(url)) zurückgeben; console.log("Multithread-Download gestartet: " + +new Date()); herunterladen({ URL (URL = URL = URL), Blockgröße: 0,1 * 1024 * 1024, PoolLimit: 6, }).then((Puffer) => { console.log("Multithread-Download endet: " + +new Date()); saveAs({ buffers, name: "Mein komprimiertes Paket", mime: "application/zip" }); }); } Da der vollständige Beispielcode ziemlich lang ist, werde ich den spezifischen Code nicht veröffentlichen. Wenn Sie interessiert sind, können Sie unter der folgenden Adresse den Beispielcode durchsuchen.
Hier sehen wir uns die Laufergebnisse des Beispiels für den Download großer Dateien an: AbschlussDieser Artikel stellt die Verwendung der von der async-pool-Bibliothek in JavaScript bereitgestellten Funktion asyncPool zum parallelen Herunterladen großer Dateien vor. Neben der Einführung der asyncPool-Funktion stellte Abaoge auch verwandtes Wissen vor, z. B. wie die Dateigröße über die HEAD-Anforderung ermittelt wird, wie HTTP-Bereichsanforderungen initiiert werden und wie Dateien auf dem Client gespeichert werden. Tatsächlich kann die asyncPool-Funktion nicht nur das parallele Herunterladen großer Dateien, sondern auch das parallele Hochladen großer Dateien realisieren. Interessierte Freunde können es selbst ausprobieren. Oben finden Sie Einzelheiten zur Implementierung des parallelen Herunterladens großer Dateien in JavaScript. Weitere Informationen zum parallelen Herunterladen großer Dateien in JavaScript finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
>>: Beispiel für eine dynamische Sperre der IP-Blacklist von Nginx
In diesem Artikel wird der spezifische Code von v...
Inhaltsverzeichnis 1. Problembeschreibung 2. Ursa...
1. Was ist Eventdelegation? Ereignisdelegierung: ...
Inhaltsverzeichnis 1. Warenkorb-Beispiel 2. Code-...
Schritt 1: Umgebungsvariablen konfigurieren (mein...
Anforderungen: Die PC-Seite und die mobile Seite ...
1. Entpacken Sie das Zip-Paket in das Installatio...
CocosCreator-Version: 2.3.4 Cocos hat keine Liste...
Inhaltsverzeichnis 1. Projektaussichten 2. Wissen...
Zwei Parameter der MySQL-Paging Wählen Sie * aus ...
Es gibt drei Seiten A, B und C. Seite A enthält Se...
In diesem Blog führe ich Sie in einfachen Schritt...
Überspringen Sie die Docker-Installationsschritte...
Im vorherigen Artikel haben wir vorgestellt, wie ...
Nach der Konfiguration der TabBar im WeChat-Apple...