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
1. Beim Öffnen der Webseite wird die Meldung „503...
Inhaltsverzeichnis Überblick Virtueller Dom Prinz...
Inhaltsverzeichnis 1. Erstellen Sie eine gespeich...
Inhaltsverzeichnis Hintergrund 1) Aktivieren Sie ...
Sie können den Befehl ps verwenden. Es kann relev...
Isolationsstufe: Isolation ist komplizierter als ...
In diesem Artikelbeispiel wird der spezifische Co...
Inhaltsverzeichnis 1. Globale Wache 1. Globale Fr...
Vorwort Die Datenbank war schon immer meine Schwa...
1.Service-Befehl Der Servicebefehl geht tatsächli...
Inhaltsverzeichnis Problembeschreibung Szenario S...
Es gibt zwei Metaattribute: Name und http-equiv. D...
Routenplanung vue-router4 behält den Großteil der...
Der Link-In-Stil besteht darin, alle Stile in ein...
Inhaltsverzeichnis Die benutzerdefinierte CSS-Var...