JavaScript implementiert die Verarbeitung großer Datei-Uploads

JavaScript implementiert die Verarbeitung großer Datei-Uploads

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.
2. Die Anforderungszeit ist zu lang und die Anforderung läuft ab.
3. Die Übertragung wird unterbrochen und muss erneut hochgeladen werden, wodurch alle bisherigen Bemühungen umsonst waren.

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.
2. Richten Sie Sharding ein. File basiert auf Blob und erbt die Funktionen von Blob. Sie können File als Unterklasse von Blob betrachten, was für die Slice-Methode von Blob praktisch ist, um File-Sharding durchzuführen und sie nacheinander hochzuladen.
3. Nachdem die Fragmentdateien hochgeladen wurden, fordern Sie das Merge-Interface-Backend auf, die Dateien zusammenzuführen.

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:
  • Beispiel für die Konvertierung von JavaScript-Datentypen (Konvertieren anderer Typen in Zeichenfolgen, numerische Typen und Boolesche Typen)
  • Beispiel für die Konvertierung eines flachen JavaScript-Arrays in eine Baumstruktur
  • Javascript implementiert die Webversion des Flipperspiels
  • JavaScript zur Implementierung der Webversion des Schlangenspiels
  • Ein Artikel zur Einführung in Java Script

<<:  Beim Einrichten von Jenkins in einer Docker-Umgebung werden im Konsolenprotokoll beim Erstellen von Aufgaben verstümmelte chinesische Zeichen angezeigt

>>:  So vergleichen Sie zwei Datenbanktabellenstrukturen in MySQL

Artikel empfehlen

Schreiben Sie einen formellen Blog mit XHTML CSS

Der vollständige Name von Blog sollte Weblog sein,...

Schiebemenü mit CSS3 implementiert

Ergebnis:Implementierungscode: <!DOCTYPE html&...

Eine kurze Einführung in die MySQL MyCat-Middleware

1. Was ist mycat Ein vollständig Open Source-Groß...

Einführung in den strikten Modus von JavaScript verwenden Sie strikt

Inhaltsverzeichnis 1. Übersicht 1.1 Was ist der s...

Die am häufigsten verwendete HTML-Escape-Sequenz

In HTML haben <, >, & usw. eine speziell...

Detaillierte Erklärung von as, Fragezeichen und Ausrufezeichen in Typescript

1. Das Schlüsselwort as gibt eine Behauptung an I...

So implementieren Sie die Größenanpassung mobiler Webseiten

Ich habe das vorliegende Projekt endlich abgeschl...

Methoden und Schritte zum Bereitstellen mehrerer War-Pakete in Tomcat

1 Hintergrund JDK1.8-u181 und Tomcat8.5.53 wurden...

Detaillierte Anweisungen zur Installation der MySQL5.7-Datenbank unter Centos7.2

Das MySQL auf dem Server ist in der Version 8.0.1...

CSS3-Animation – Erläuterung der Funktion „Steps“

Als ich mir in letzter Zeit einige CSS3-Animation...

Lösen Sie das Problem des Ablaufs des TLS-Zertifikats (SSL) von Docker

Problemphänomen: [root@localhost ~]# Docker-Image...