Beim Hochladen von Dateien, z. B. Videodateien, die nur einige zehn MB oder über 1 GB groß sind, treten beim Senden von Daten mit der normalen HTTP-Anforderungsmethode häufig die folgenden Probleme auf: 1. Die Datei ist zu groß und überschreitet die Anforderungsgrößenbeschränkung des Servers. Diese Probleme beeinträchtigen die Benutzererfahrung erheblich. Daher wird im Folgenden eine Lösung für die Dateisegmentierung und den Upload auf Basis von nativem JavaScript vorgestellt. Der konkrete Implementierungsprozess ist wie folgt: 1. Holen Sie sich das Dateiobjekt über DOM, führen Sie eine MD5-Verschlüsselung für die Datei durch (Dateiinhalt + Dateititelformat) und verwenden Sie SparkMD5, um die Datei zu verschlüsseln. 1. Datei hochladen Seite <!DOCTYPE html> <html lang="de"> <Kopf> <meta charset="UTF-8"> <meta name="viewport" content="width=Gerätebreite, Anfangsmaßstab=1.0"> <meta http-equiv="X-UA-kompatibel" content="ie=edge"> <title>Datei-Upload</title> <script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script> <script src="https://code.jquery.com/jquery-3.4.1.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.0/spark-md5.js"></script> <Stil> /* Benutzerdefinierter Fortschrittsbalkenstil */ .precent Eingabe[Typ=Bereich] { -webkit-auftritt: keines; /*Standardstil des Systems löschen*/ Breite: 7,8rem; /* Hintergrund: -webkit-linear-gradient(#ddd, #ddd) keine Wiederholung, #ddd; */ /*Setze die linke Farbe auf #61bd12 und die rechte Farbe auf #ddd*/ Hintergrundgröße: 75 % 100 %; /*Linkes und rechtes Breitenverhältnis festlegen*/ Höhe: 0,6rem; /*Höhe des Balkens*/ Randradius: 0,4rem; Rand: 1px durchgezogen #ddd; Box-Schatten: 0 0 10px rgba(0,0,0,.125) Einschub; } /*Blockstil ziehen*/ .precent Eingabe [Typ=Bereich]::-webkit-slider-thumb { -webkit-auftritt: keines; /*Standardstil des Systems löschen*/ Höhe: .9rem; /*Blockhöhe ziehen*/ Breite: .9rem; /*Blockbreite ziehen*/ Hintergrund: #fff; /*Blockhintergrund ziehen*/ Randradius: 50 %; /*Stellen Sie das Erscheinungsbild auf rund ein*/ Rand: durchgezogen 1px #ddd; /*Rahmen festlegen*/ } </Stil> </Kopf> <Text> <h1>Test zum Hochladen großer Dateien in mehreren Teilen</h1> <div> <input id="Datei" Typ="Datei" Name="Avatar" /> <div Stil="Padding: 10px 0;"> <input id="submitBtn" type="button" value="Senden" /> <input id="pauseBtn" type="button" value="Pause" /> </div> <div Klasse="vorläufig"> <Eingabetyp="Bereich" Wert="0" /><span id="precentVal">0 %</span> </div> </div> <script type="text/javascript" src="./js/index.js"></script> </body> </html> 2. Große Dateien in Stücken hochladen $(Dokument).bereit(() => { const submitBtn = $('#submitBtn'); //Senden-Schaltfläche const precentDom = $(".precent input")[0]; //Fortschrittsbalken const precentVal = $("#precentVal"); //Fortschrittsbalkenwert entspricht dom const pauseBtn = $('#pauseBtn'); // Pause-Taste // Die Größe jedes Blocks ist auf 1 Megabyte eingestellt const chunkSize = 1 * 1024 * 1024; // Holen Sie sich die Slice-Methode und machen Sie sie kompatibel const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; // MD5-Verschlüsselung der Datei (Dateiinhalt + Dateititelformat) const hashFile = (Datei) => { returniere neues Promise((lösen, ablehnen) => { const chunks = Math.ceil(Dateigröße / Chunkgröße); lass currentChunk = 0; const spark = neuer SparkMD5.ArrayBuffer(); const fileReader = neuer FileReader(); Funktion loadNext() { const start = aktueller Chunk * Chunkgröße; const end = start + chunkSize >= Dateigröße? Dateigröße: start + chunkSize; fileReader.readAsArrayBuffer(blobSlice.call(Datei, Start, Ende)); } fileReader.onload = e => { spark.append(e.target.result); // Array-Puffer anhängen aktuellerChunk += 1; wenn (aktuellerChunk < chunks) { ladenWeiter(); } anders { console.log('Laden abgeschlossen'); const Ergebnis = Spark.Ende(); // MD5-Verschlüsselung nach Inhalt und Dateiname const sparkMd5 = new SparkMD5(); sparkMd5.append(Ergebnis); sparkMd5.append(Datei.Name); const hexHash = sparkMd5.end(); auflösen(hexHash); } }; fileReader.onerror = () => { console.warnen('Das Lesen der Datei ist fehlgeschlagen!'); }; ladenWeiter(); }).catch(err => { console.log(fehler); }); } // Senden submitBtn.on('click', async () => { var pauseStatus = false; var nowUploadNums = 0 // 1. Datei lesen const fileDom = $('#file')[0]; const-Dateien = fileDom.files; const Datei = Dateien[0]; wenn (!Datei) { alert('Keine Datei erhalten'); zurückkehren; } // 2. Setze die Sharding-Parameterattribute und hole den MD5-Wert der Datei const hash = await hashFile(file); //Datei-Hash const blockCount = Math.ceil(file.size / chunkSize); // Gesamtzahl der Shards const axiosPromiseArray = []; // axiosPromise-Array // Datei-Upload const uploadFile = () => { const start = jetztUploadNums * chunkSize; const end = Math.min(Dateigröße, Start + Blockgröße); // Formular erstellen const form = new FormData(); // Die Methode blobSlice.call(file, start, end) wird zum Datei-Slicing verwendet form.append('file', blobSlice.call(file, start, end)); form.append('index', jetztUploadNums); form.append('hash', hash); // Ajax übermittelt Fragmente und der Inhaltstyp ist multipart/form-data const axiosOptions = { beimUploadProgress: e => { jetztUploadNums++; // Bestimmen Sie, ob der Upload des Fragments abgeschlossen ist, wenn (nowUploadNums < blockCount) { setPrecent(jetztUploadNums, Blockanzahl); UploadFile(jetztUploadNums) } anders { // 4. Nachdem alle Shards hochgeladen wurden, fordern Sie die Zusammenführung der Shard-Dateien an axios.all(axiosPromiseArray).then(() => { setPrecent(blockCount, blockCount); // Alle Uploads abgeschlossen axios.post('/file/merge_chunks', { Name: Dateiname, gesamt: blockCount, Hash }).dann(res => { console.log(res.data, Datei); pauseStatus = falsch; alert('Hochladen erfolgreich'); }).catch(err => { console.log(fehler); }); }); } }, }; // Zum Promise-Array hinzufügen if (!pauseStatus) { axiosPromiseArray.push(axios.post('/Datei/Hochladen', Formular, axiosOptions)); } } //Setze die Fortschrittsbalkenfunktion setPrecent(now, total) { var prencentValue = ((jetzt / gesamt) * 100).toFixed(2) precentDom.value = precentWert precentVal.text(precentValue + '%') precentDom.style.cssText = `Hintergrund:-webkit-linear-gradient(oben, #059CFA, #059CFA) 0 % 0 % / ${prencentValue} % 100 % keine Wiederholung` } // Pause pauseBtn.on('click', (e) => { pauseStatus = !pauseStatus; e.currentTarget.value = pauseStatus ? 'Start' : 'Pause' if (!pauseStatus) { UploadFile(jetztUploadNums) } }) Datei hochladen(); }); }) 3. Datei-Upload und Zusammenführen der Shard-Dateischnittstelle (Knoten) const Router = erforderlich('koa-router'); const multer = require('koa-multer'); const fs = erfordern('fs-extra'); const path = require('Pfad'); const router = neuer Router(); const { mkdirsSync } = require('../utils/dir'); const uploadPath = path.join(__dirname, 'upload'); const chunkUploadPath = Pfad.join(uploadPath, 'temp'); const upload = multer({ dest: chunkUploadPath }); // Schnittstelle zum Hochladen von Dateien router.post('/file/upload', upload.single('file'), async (ctx, next) => { const { index, hash } = ctx.req.body; const chunksPath = path.join(chunkUploadPath, hash, '/'); if(!fs.existsSync(chunksPath)) mkdirsSync(chunksPath); fs.renameSync(ctx.req.file.path, chunksPath + hash + '-' + index); ctx.status = 200; ctx.res.end('Erfolgreich'); }) // Fragmentdateischnittstelle zusammenführen router.post('/file/merge_chunks', async (ctx, next) => { const { Name, Gesamt, Hash } = ctx.request.body; const chunksPath = path.join(chunkUploadPath, hash, '/'); const filePath = Pfad.Join(UploadPath, Name); // Alle Chunks lesen const chunks = fs.readdirSync(chunksPath); // Speicherdatei erstellen fs.writeFileSync(filePath, ''); wenn (chunks.length !== gesamt || chunks.length === 0) { ctx.status = 200; ctx.res.end('Die Anzahl der Slice-Dateien stimmt nicht überein'); zurückkehren; } für (sei i = 0; i < gesamt; i++) { // An die Datei anhängen fs.appendFileSync(filePath, fs.readFileSync(chunksPath + hash + '-' +i)); // Lösche den diesmal verwendeten Block fs.unlinkSync(chunksPath + hash + '-' +i); } fs.rmdirSync(chunksPath); // Die Dateien wurden erfolgreich zusammengeführt und die Dateiinformationen können in der Datenbank gespeichert werden. ctx.status = 200; ctx.res.end('Erfolgreich'); }) Das Obige ist der grundlegende Prozess des Hochladens von Dateien in Teilen. Der Upload-Fortschrittsbalken sowie die Vorgänge „Pause“ und „Hochladen starten“ werden während des Prozesses hinzugefügt. Siehe den detaillierten Code Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird. Das könnte Sie auch interessieren:
|
>>: So vergleichen Sie zwei Datenbanktabellenstrukturen in MySQL
Informationen zur Bedienung finden Sie hier in de...
Inhaltsverzeichnis Vorwort 1. Binärer Baum 1.1. D...
1.core-Datei Wenn während der Programmausführung ...
MySQL erstellt Benutzer und autorisiert und wider...
Inhaltsverzeichnis 1. filter() 2. fürJedes() 3. e...
Inhaltsverzeichnis Was ist das Linux-System, das ...
1 Herunterladen Die Adresse lautet: https://dev.m...
Inhaltsverzeichnis 1. Einfacher Datenabruf 2. Dat...
Vorwort Bei der Linux-Kernel-Programmierung werde...
Vue $set Array-Sammlungsobjektzuweisung In der be...
Nach der MySQL-Datenbankoptimierung kann nicht nu...
eins. Vorwort <br />Sie werden diese Art von...
Inhaltsverzeichnis verwenden Installieren Wie wir...
Fall 1: Letzte Übermittlung und kein Push Führen ...
Führen Sie kein Front-End-UI-Framework ein, es se...