Node.js implementiert die Wiederaufnahme von Haltepunkten

Node.js implementiert die Wiederaufnahme von Haltepunkten

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 vor dem Hochladen jedes Slices die Serverschnittstelle auf, die Anzahl der hochgeladenen Slices derselben Datei zu lesen
  • Wenn es sich bei der hochgeladenen Datei um eine neue Datei handelt, 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: github.com/Surprise-li…

Oben finden Sie Einzelheiten zur Implementierung der Breakpoint-Wiederaufnahme in Node.js. Weitere Informationen zur Breakpoint-Wiederaufnahme in Node.js finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

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
  • Implementierung der Breakpoint-Wiederaufnahme in Node.js
  • React+Node realisiert die Idee, große Dateien stückweise hochzuladen und den Upload in Sekundenschnelle fortzusetzen

<<:  Grafisches Tutorial zur Installation und Konfiguration von MySQL 8.0.15 unter Win10 Home Version 64

>>:  Probleme beim Upgrade von Python und der Installation von Mongodb-Treibern unter Centos

Artikel empfehlen

Dinge, die Sie nicht über die CSS-Pseudoelemente ::before und ::after wissen

CSS hat zwei Pseudoklassen, die nicht häufig verw...

JavaScript-Entwurfsmuster – Muster der Verantwortungskette

Inhaltsverzeichnis Überblick Code-Implementierung...

Analyse der problematischen „Aborted“-Warnung in MySQL anhand von Fallstudien

Dieser Artikel stellt hauptsächlich den relevante...

MySQL-Transaktions-Tutorial Yii2.0 Händler-Auszahlungsfunktion

Vorwort Ich bin ein PHP-Programmierer, der als Pr...

CSS3 zum Erreichen eines Menü-Hover-Effekts

Ergebnis: html <nav id="nav-1"> &...

Mysql-Operation zum Abrufen von Tabellenkommentarfeldern

Ich werde nicht viel Unsinn erzählen, schauen wir...

Detaillierte Erklärung des einfachen Stores von Vue

Die einfachste Store-Anwendung in Vue ist die glo...

Detailliertes Tutorial zur Installation von MySQL 8.0.20 auf CentOS7.8

1. MySQL-Software installieren Laden Sie das offi...

So invertieren Sie die Implementierung einer Bézierkurve in CSS

Schauen wir uns zunächst einen CSS-Karussell-Anim...