Implementierung der Breakpoint-Wiederaufnahme in Node.js

Implementierung der Breakpoint-Wiederaufnahme in Node.js

Vorwort

Normaler Geschäftsbedarf: Hochladen von Bildern, Excel usw. Schließlich können Dateien mit mehreren MB Größe schnell auf den Server hochgeladen werden.
Beim Hochladen großer Dateien, z. B. Videos mit einer Größe von mehreren hundert MB oder GB, müssen Sie länger warten.

Dies führt zu einer entsprechenden Lösung. Bei Pausen, Verbindungsabbrüchen und schlechten Netzwerkbedingungen beim Hochladen großer Dateien kann die Verwendung von Slicing + Breakpoint Resume die oben genannten Situationen gut bewältigen.

Lösungsanalyse

Scheibe

Es dient zum Aufteilen des hochgeladenen Videos. Die spezifischen Vorgänge sind:

File.slice(start,end): gibt ein neues Blob-Objekt zurück

  • Kopieren Sie die Startbytes des Blobs
  • Kopieren Sie das Endbyte des Blobs

Lebenslauf herunterladen

Fordern Sie die Serverschnittstelle vor dem Hochladen jedes Slices auf, die Anzahl der hochgeladenen Slices derselben Datei zu lesen. Wenn eine neue Datei hochgeladen wird, gibt der Server 0 zurück, andernfalls gibt er die Anzahl der hochgeladenen Slices zurück.

Spezifischer Lösungsprozess

Diese Demo stellt wichtige Ideen und Methoden vor. Weitere Funktionen wie Dateibeschränkungen, lastModifiedDate-Überprüfung von Dateiduplikationen, regelmäßiges Löschen zwischengespeicherter Dateien und andere Funktionserweiterungen können auf Grundlage dieses Codes hinzugefügt werden.

html

<input Klasse="Video" Typ="Datei" />
<button type="senden" onclick="handleVideo(event, '.video', 'video')">
    Senden</button>

Skript

let count = 0; // Zeichne den hochzuladenden Dateiindex auf const handleVideo = async (event, name, url) => {
// Standardformularereignisse des Browsers verhindern event.preventDefault();
Lassen Sie aktuelle Größe = document.querySelector("h2");
let Dateien = document.querySelector(name).files;
//Standardanzahl der Slices const sectionLength = 100;
// Zuerst die Schnittstelle anfordern, um zu prüfen, ob die Datei auf dem Server vorhanden ist // Wenn count 0 ist, handelt es sich um den ersten Upload. Wenn count ungleich 0 ist, ist die Datei auf dem Server vorhanden und die Anzahl der hochgeladenen Slices wird zurückgegeben count = await handleCancel(files[0]);

//Deklariere das Array-Objekt, das den Slice speichert let fileCurrent = [];
// Schleife Datei Dateiobjekt für (const file of [...files]) {
  //Größe jedes Segments ermitteln let itemSize = Math.ceil(file.size / sectionLength);
  // Dateigrößen durchlaufen und Dateiblobs im Array speichern let current = 0;
  für (aktuell; aktuell < Dateigröße; aktuell += Elementgröße) {
    fileCurrent.push({ Datei: file.slice(aktuell, aktuell + Artikelgröße) });
  }
  // axios simuliert manuelle Stornierungsanforderung const CancelToken = axios.CancelToken;
  const Quelle = CancelToken.source();
  // Wenn Sie den Upload fortsetzen, verarbeiten Sie die Anzahl der Slices. Wenn die hochgeladenen Slices bereits hochgeladen wurden, ist keine erneute Anforderung zum Hochladen erforderlich. fileCurrent =
    Anzahl === 0? Dateiaktuell: Dateiaktuell.slice(Anzahl, Abschnittslänge);
  // Loop-Slice-Anforderungsschnittstelle für (const [Index, Element] von fileCurrent.entries()) {
    //Anforderungspause simulieren||Netzwerk getrenntif (Index > 90) {
      source.cancel("Anfrage abbrechen");
    }
    // Dateibezogene Informationen speichern // Datei ist ein Slice-Blob-Objekt // Dateiname ist der Dateiname // Index ist die aktuelle Slice-Nummer // total ist die Gesamtzahl der Slices let formData = new FormData();
    formData.append("Datei", item.file);
    formData.append("Dateiname", Dateiname);
    formData.append("total", Abschnittslänge);
    formData.append("index", index + count + 1);

    warte auf Axios({
      URL: `http://localhost:8080/${url}`,
      Methode: "POST",
      Daten: Formulardaten,
      cancelToken: Quelltoken,
    })
      .then((Antwort) => {
        // Daten zur Anzeige des Fortschritts zurückgeben currentSize.innerHTML = `progress${response.data.size}%`;
      })
      .catch((err) => {
        console.log(fehler);
      });
  }
}
};

// Request-Schnittstelle, um zu prüfen, ob die hochgeladene Datei existiert // count ist 0, was bedeutet, dass sie nicht existiert. Wenn count ungleich 0 ist, wurde die entsprechende Anzahl an Slices hochgeladen const handleCancel = (file) => {
returniere Axios({
  Methode: "post",
  URL: "http://localhost:8080/getSize",
  Header: { "Inhaltstyp": "application/json; Zeichensatz = utf-8" },
  Daten: {
    Dateiname: Dateiname,
  },
})
  .then((res) => {
    gibt res.data.count zurück;
  })
  .catch((err) => {
    console.log(fehler);
  });
};

Knotenserver

// Verwenden Sie Express, um die Server-API zu erstellen
const express = erfordern("express");
//Den Logikcode zum Hochladen von Dateien einführen const upload = require("./upload_file");
// Alle Antworten verarbeiten und domänenübergreifend festlegen app.all("*", (req, res, next) => {
  res.header("Zugriffskontrolle-Origin zulassen", "*");
  res.header("Zugriffskontrolle-Header zulassen", "X-Angefordert-Mit");
  res.header("Zugriffskontrolle-Zulassen-Methoden", "PUT, POST, GET, DELETE, OPTIONS");
  res.header("Zugriffskontrolle-Header zulassen", "Inhaltstyp, X-Angefordert-Mit");
  res.header("X-Powered-By", " 3.2.1");
  res.header("Inhaltstyp", "application/json;charset=utf-8");
  nächste();
});
const app = express();

app.use(bodyParser.json({ Typ: "application/*+json" }));
// Video-Upload (Abfrage der aktuellen Slice-Anzahl)
app.post("/getSize", hochladen.getSize);
// Schnittstelle zum Hochladen von Videos app.post("/video", upload.video);

// Lokales Port-Listening aktivieren app.listen(8080);

Datei hochladen

// Datei-Upload-Modul const formidable = require("formidable");
// Dateisystemmodul const fs = require("fs");
//Systempfadmodul const path = require("path");

//Operation zum Schreiben des Dateistreams const handleStream = (item, writeStream) => {
  // Den entsprechenden Verzeichnisdateipuffer lesen
  const readFile = fs.readFileSync(Element);
  // Schreibe den Lesepuffer || Block in den Stream writeStream.write(readFile);
  // Nach dem Schreiben die temporär gespeicherte Slice-Datei löschen fs.unlink(item, () => {});
};

// Video-Upload (Ausschnitt)
modul.exports.video = (erf, res) => {
  // Analyseobjekt erstellen const form = new formidable.IncomingForm();
  // Legen Sie den Upload-Pfad für die Videodatei fest let dirPath = path.join(__dirname, "video");
  form.uploadDir = Verzeichnispfad;
  // Ob das hochgeladene Dateinamenssuffix beibehalten werden soll form.keepExtensions = true;
  // err Fehlerobjekt enthält Fehlerinformationen, wenn die Analyse fehlschlägt // fields enthält formData-Schlüsselwertobjekte außer binären // file Objekttypinformationen zu hochgeladenen Dateien form.parse(req, async (err, fields, file) => {
    // Holen Sie das hochgeladene Datei-Blob-Objekt let files = file.file;
    // Den aktuellen Slice-Index abrufen
    let index = Felder.index;
    // Gesamtanzahl der Slices abrufen let total = fields.total;
    // Dateinamen abrufen let filename = fields.filename;
    // Schreibe den Upload-Dateinamen neu und lege das temporäre Verzeichnis fest let url =
      Verzeichnispfad +
      "/" +
      dateiname.split(".")[0] +
      `_${index}.` +
      Dateiname.split(".")[1];
    versuchen {
      // Den hochgeladenen Dateinamen synchron ändern fs.renameSync(files.path, url);
      konsole.log(url);
      // Asynchrone Verarbeitung setTimeout(() => {
        // Bestimmen Sie, ob der letzte Slice hochgeladen wurde und schreiben Sie alle Videos zusammen, wenn (Index === total) {
          // Synchron ein neues Verzeichnis zum Speichern des kompletten Videos erstellen let newDir = __dirname + `/uploadFiles/${Date.now()}`;
          // Verzeichnis erstellen fs.mkdirSync(newDir);
          // Erstellen Sie einen beschreibbaren Stream zum Schreiben in die Datei let writeStream = fs.createWriteStream(newDir + `/${filename}`);
          lass fsList = [];
          // Alle Slice-Dateien herausnehmen und in ein Array einfügen for (let i = 0; i < total; i++) {
            const fsUrl =
              Verzeichnispfad +
              "/" +
              dateiname.split(".")[0] +
              `_${i + 1}.` +
              Dateiname.split(".")[1];
            fsList.push(fsUrl);
          }
          // Durchlaufe das Slice-Datei-Array und schreibe in den Stream für (let item of fsList) {
            Stream behandeln(Element, Stream schreiben);
          }
          // Alles schreiben und Stream schließen write stream writeStream.end();
        }
      }, 100);
    } fangen (e) {
      konsole.log(e);
    }
    res.send({
      Code: 0,
      Nachricht: "Hochladen erfolgreich",
      Größe: Index,
    });
  });
};

// Anzahl der Dateisegmente abrufen module.exports.getSize = (req, res) => {
  lass count = 0;
  req.setEncoding("utf8");
  req.on("Daten", Funktion (Daten) {
    let name = JSON.parse(Daten);
    let dirPath = path.join(__dirname, "video");
    // Anzahl der hochgeladenen Slice-Dateien berechnen let files = fs.readdirSync(dirPath);
    files.forEach((item, index) => {
      lass url =
        name.dateiName.split(".")[0] +
        `_${index + 1}.` +
        name.dateiName.split(".")[1];
      wenn (Dateien.includes(URL)) {
        ++zählen;
      }
    });
    res.send({
      Code: 0,
      msg: "Bitte mit dem Hochladen fortfahren",
      zählen,
    });
  });
};

Logische Analyse

Frontend

Fordern Sie zunächst den Upload an, um zu prüfen, ob die Datei zum ersten Mal hochgeladen wird oder der entsprechende Slice bereits vorhanden ist

  • Wenn die Datei zum ersten Mal hochgeladen wird, beginnt der Slice bei 0
  • Wenn die Datei bereits über ein entsprechendes Slice verfügt, beginnt die Upload-Anforderung bei der Slice-Nummer.

Durchlaufen Sie das Slice-Array und laden Sie jede Slice-Datei hoch

  • Es verwendet eine simulierte manuelle Pausenanforderung und bricht die Anforderung ab, wenn die Anzahl der Slices größer als 90 ist.

Server

Empfangen Sie den Dateinamen der Abfragedatei, suchen Sie die Adresse der temporären Speicherdatei und stellen Sie fest, ob die entsprechende hochgeladene Datei vorhanden ist

  • Wenn die Datei noch nie hochgeladen wurde, wird 0 zurückgegeben und die Slice-Nummer beginnt bei 0.
  • Wenn die Datei hochgeladen wurde, wird die entsprechende Anzahl an Slices zurückgegeben

Empfangen Sie hochgeladene Dateisegmente und speichern Sie die Dateien in einem temporären Speicherverzeichnis

  • Verwenden Sie „Anzahl“ und „Gesamt“, um zu bestimmen, ob der Slice hochgeladen wurde.
  • Erstellen Sie nach dem Hochladen ein Dateispeicherverzeichnis und einen beschreibbaren Stream zum Schreiben.
  • Extrahieren Sie die entsprechenden temporären Dateien und legen Sie sie in das Array, durchlaufen Sie das Dateiverzeichnis-Array und lesen und schreiben Sie den Dateipuffer nacheinander
  • Schließen Sie nach dem Schreiben den beschreibbaren Stream.

Zusammenfassung

Der obige Code kann je nach spezifischem Geschäftsprozess geändert oder davon abgewichen werden. Dies ist nur eine der spezifischen Implementierungsmethoden.
Ich hoffe, dieser Artikel kann für alle hilfreich sein. Wenn der Text Fehler enthält, hoffe ich, dass Sie mich darauf hinweisen können.

Die obige Codeadresse: https://github.com/Surprise-ling/uploadFiles

Dies ist das Ende dieses Artikels über die Implementierung der Node.js-Breakpoint-Wiederaufnahme. Weitere relevante Inhalte zur Node.js-Breakpoint-Wiederaufnahme finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Beispiel für das Hochladen großer Dateien in Teilen basierend auf Node.js
  • Zusammenfassung der Prinzipien und Methoden zur Wiederaufnahme von Datei-Haltepunkten in Node
  • Node.js implementiert die Wiederaufnahme von Haltepunkten
  • React+Node realisiert die Idee, große Dateien stückweise hochzuladen und den Upload in Sekundenschnelle fortzusetzen

<<:  Detaillierte Erklärung zum effizienten Importieren mehrerer SQL-Dateien in MySQL

>>:  Detaillierte Erklärung der Standort- und Umschreibenutzung in nginx

Artikel empfehlen

Detaillierte Analyse des Linux-NFS-Mechanismus anhand von Fällen

In Fortsetzung des vorherigen Artikels erstellen ...

So verwenden Sie Standardwerte für Variablen in SASS

Bei in SASS definierten Variablen überschreibt de...

Der praktische Prozess des Login-Status-Managements im vuex-Projekt

Inhaltsverzeichnis Werkzeug: Anmeldeszenario: übe...

Einfaches Tutorial zur Verwendung von Navicat für MySQL

empfehlen: Detailliertes Tutorial zur Registrieru...

40 Schriftarten, empfohlen für berühmte Website-Logos

Wissen Sie, welche Schriftarten in den Logo-Desig...

Detaillierte Erklärung zur Verwendung von this.$set in Vue

Inhaltsverzeichnis Verwendung von this.$set in Vu...

Detaillierte Erklärung der Vue-Filter

<Text> <div id="Wurzel"> &l...

Hinweise zu Linux-Systembefehlen

Dieser Artikel beschreibt die Linux-Systembefehle...

JavaScript-Canvas zum Laden von Bildern

In diesem Artikel wird der spezifische Code von J...

Implementierung einer geplanten Sicherung in Mysql5.7

1. Suchen Sie mysqldump.exe im MySQL-Installation...