Node.jsはブレークポイント再開を実装する

Node.jsはブレークポイント再開を実装する

ソリューション分析

スライス

  • アップロードした動画を分割します。具体的な操作は以下のとおりです。
  • File.slice(start,end): 新しいblobオブジェクトを返します
    • BLOBの開始バイトをコピーする
    • BLOBの最後のバイトをコピーする

履歴書のダウンロード

  • 各スライスをアップロードする前に、同じファイルのアップロードされたスライスの数を読み取るようにサーバーインターフェースに要求します。
  • アップロードされたファイルが新しいファイルの場合、サーバーは 0 を返します。それ以外の場合は、アップロードされたスライスの数を返します。

具体的な解決プロセス

このデモでは、重要なアイデアとメソッドが紹介されています。このコードに基づいて、ファイル制限、ファイル重複の lastModifiedDate 検証、キャッシュされたファイルの定期的なクリア、その他の機能拡張などの他の機能を追加できます。

html

<input class="ビデオ" type="ファイル" />
<button type="submit" onclick="handleVideo(event, '.video', 'video')">
    送信</button>

スクリプト

let count = 0; // アップロードするファイルインデックスを記録する const handleVideo = async (event, name, url) => {
// ブラウザのデフォルトのフォームイベントを防止する event.preventDefault();
currentSize を document.querySelector("h2") に設定します。
files = document.querySelector(name).files とします。
// デフォルトのスライス数 const sectionLength = 100;
// 最初にインターフェイスに要求して、サーバー上にファイルが存在するかどうかを確認します // count が 0 の場合、最初のアップロードです。count が 0 でない場合、ファイルはサーバー上に存在し、アップロードされたスライスの数が返されます count = await handleCancel(files[0]);

//スライスを格納する配列オブジェクトを宣言します。let fileCurrent = [];
// ループファイルファイルオブジェクト for (const file of [...files]) {
  // 各スライスのサイズを取得します。let itemSize = Math.ceil(file.size / sectionLength);
  // ファイル サイズをループし、ファイル BLOB を配列に格納します。let current = 0;
  (現在値; 現在値 < ファイルサイズ; 現在値 += アイテムサイズ) {
    fileCurrent.push({ ファイル: file.slice(current, current + itemSize) });
  }
  // axios は手動キャンセル要求をシミュレートします。const CancelToken = axios.CancelToken;
  const ソース = CancelToken.source();
  // アップロードを再開するときに、スライスの数を処理します。アップロードされたスライスがすでにアップロードされている場合は、再度アップロードを要求する必要はありません。fileCurrent =
    count === 0 ? fileCurrent: fileCurrent.slice(count, sectionLength);
  // ループスライスリクエストインターフェース for (const [index, item] of fileCurrent.entries()) {
    //リクエストの一時停止をシミュレートする||ネットワークが切断された場合if (index > 90) {
      source.cancel("リクエストをキャンセル");
    }
    // ファイル関連情報を保存します // ファイルはスライス BLOB オブジェクトです // ファイル名はファイル名です // インデックスは現在のスライス番号です // 合計は合計スライス数です let formData = new FormData();
    formData.append("ファイル", item.file);
    formData.append("ファイル名", file.name);
    formData.append("total", sectionLength);
    formData.append("index", インデックス + カウント + 1);

    待機axios({
      URL: `http://localhost:8080/${url}`,
      メソッド: "POST",
      データ: フォームデータ、
      キャンセルトークン: ソーストークン、
    })
      .then((応答) => {
        // 進捗状況を表示するためのデータを返します currentSize.innerHTML = `progress${response.data.size}%`;
      })
      .catch((エラー) => {
        コンソールログ(エラー);
      });
  }
}
};

// アップロードされたファイルが存在するかどうかを確認するためのリクエストインターフェース // count が 0 の場合、存在しないことを意味します。count が 0 でない場合、対応する数のスライスがアップロードされています。const handleCancel = (file) => {
戻り値: axios({
  メソッド: "post",
  URL: "http://localhost:8080/getSize",
  ヘッダー: { "Content-Type": "application/json; charset = utf-8" },
  データ: {
    ファイル名: ファイル名、
  },
})
  .then((res) => {
    res.data.count を返します。
  })
  .catch((エラー) => {
    コンソールログ(エラー);
  });
};

ノードサーバー

// Express を使用してサーバー API を構築します
定数 express = require("express");
// ファイルをアップロードするためのロジックコードを導入します。const upload = require("./upload_file");
// すべての応答を処理し、クロスドメインを設定します app.all("*", (req, res, next) => {
  res.header("アクセス制御許可オリジン", "*");
  res.header("アクセス制御許可ヘッダー", "X-Requested-With");
  res.header("アクセス制御許可メソッド", "PUT、POST、GET、DELETE、OPTIONS");
  res.header("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
  res.header("X-Powered-By", " 3.2.1");
  res.header("Content-Type", "application/json;charset=utf-8");
  次();
});
express() は、定数です。

app.use(bodyParser.json({ type: "application/*+json" }));
// ビデオのアップロード(現在のスライス数を照会)
app.post("/getSize", upload.getSize);
// ビデオアップロードインターフェース app.post("/video", upload.video);

// ローカルポートのリスニングを有効にする app.listen(8080);

アップロードファイル

// ファイルアップロードモジュール const formidable = require("formidable");
// ファイル システム モジュール const fs = require("fs");
// システムパスモジュール const path = require("path");

//ファイルストリームへの書き込み操作 const handleStream = (item, writeStream) => {
  // 対応するディレクトリファイルバッファを読み取る
  const readFile = fs.readFileSync(item);
  // 読み取りバッファ || チャンクをストリームに書き込みます writeStream.write(readFile);
  // 書き込み後、一時的に保存したスライスファイルをクリアします。fs.unlink(item, () => {});
};

// ビデオアップロード(スライス)
module.exports.video = (req, res) => {
  // 解析オブジェクトを作成します。const form = new formidable.IncomingForm();
  // ビデオファイルのアップロードパスを設定します。let dirPath = path.join(__dirname, "video");
  フォームにアップロードするDirを指定します。
  // アップロードされたファイル名のサフィックスを保持するかどうか form.keepExtensions = true;
  // err エラーオブジェクトには、解析が失敗した場合のエラー情報が含まれます // fields には、バイナリ以外の formData キーと値のオブジェクトが含まれます // file オブジェクトタイプには、アップロードされたファイルに関する情報が含まれます form.parse(req, async (err, fields, file) => {
    // アップロードされたファイル BLOB オブジェクトを取得します。let files = file.file;
    // 現在のスライスのインデックスを取得します
    index = fields.index; とします。
    // スライスの合計数を取得します。let total = fields.total;
    // ファイル名を取得します。let filename = fields.filename;
    // アップロードファイル名を書き換えて一時ディレクトリを設定する let url =
      ディレクトリパス +
      "/" +
      ファイル名.split(".")[0] +
      `_${インデックス}.` +
      ファイル名.split(".")[1];
    試す {
      // アップロードされたファイル名を同期的に変更します fs.renameSync(files.path, url);
      コンソールにログ出力します。
      // 非同期処理 setTimeout(() => {
        // 最後のスライスがアップロードされたかどうかを判断し、すべてのビデオをまとめて書き込みます if (index === total) {
          // 完全なビデオを保存するための新しいディレクトリを同期的に作成します。let newDir = __dirname + `/uploadFiles/${Date.now()}`;
          // ディレクトリを作成します fs.mkdirSync(newDir);
          // ファイルに書き込むための書き込み可能なストリームを作成します。let writeStream = fs.createWriteStream(newDir + `/${filename}`);
          fsList = [] とします。
          // すべてのスライスファイルを取り出して配列に格納します for (let i = 0; i < total; i++) {
            定数fsUrl =
              ディレクトリパス +
              "/" +
              ファイル名.split(".")[0] +
              `_${i + 1}.` +
              ファイル名.split(".")[1];
            fsList.push(fsUrl);
          }
          // スライスファイル配列をループし、ストリームに書き込みます for (let item of fsList) {
            handleStream(アイテム、writeStream);
          }
          // すべてを書き込んでストリームを閉じます write stream writeStream.end();
        }
      }, 100);
    } キャッチ (e) {
      コンソールログ(e);
    }
    res.send({
      コード: 0,
      メッセージ: 「アップロード成功」、
      サイズ: インデックス、
    });
  });
};

// ファイルスライスの数を取得します module.exports.getSize = (req, res) => {
  count = 0 とします。
  エンコードを"utf8"に設定します。
  req.on("データ", 関数(データ) {
    name = JSON.parse(データ) とします。
    dirPath = path.join(__dirname, "video"); とします。
    // アップロードされたスライスファイルの数を計算します。let files = fs.readdirSync(dirPath);
    files.forEach((アイテム, インデックス) => {
      URLを=にする
        名前.ファイル名.split(".")[0] +
        `_${インデックス + 1}.` +
        名前.ファイル名.split(".")[1];
      if (files.includes(url)) {
        ++カウント;
      }
    });
    res.send({
      コード: 0,
      メッセージ: 「アップロードを続けてください」
      カウント、
    });
  });
};

論理的分析

フロントエンド

  • まず、アップロードをリクエストして、ファイルが初めてアップロードされたものか、対応するスライスがすでに存在するかを確認します。
    • ファイルが初めてアップロードされると、スライスは0から始まります。
    • ファイルにすでに対応するスライスがある場合、アップロード要求はスライス番号から開始されます。
  • スライス配列をループし、各スライスファイルをアップロードします。
    • 手動一時停止要求をシミュレートし、スライス数が90を超えると要求をキャンセルします。

サーバ

  • クエリファイルのファイル名を受け取り、一時保存ファイルのアドレスを見つけ、対応するアップロードファイルが存在するかどうかを判断します。
    • ファイルが一度もアップロードされていない場合は 0 を返し、スライス番号は 0 から始まります。
    • ファイルがアップロードされている場合は、対応するスライスの数が返されます。
  • アップロードされたファイルスライスを受信し、一時ストレージディレクトリにファイルを保存します。
    • count と total を使用して、スライスがアップロードされたかどうかを判断します。
    • アップロード後、ファイル保存ディレクトリを作成し、書き込み用の書き込み可能なストリームを作成します。
    • 対応する一時ファイルを抽出して配列に入れ、ファイルディレクトリ配列をループし、ファイルバッファを順番に読み書きします。
    • 書き込み後、書き込み可能なストリームを閉じます。

まとめ

上記のコードは、具体的な業務プロセスに応じて変更または逸脱する可能性があります。これは、具体的な実装方法の 1 つにすぎません。
この記事が皆様のお役に立てれば幸いです。文章に間違いがありましたらご指摘いただければ幸いです。

上記コードのアドレス: github.com/Surprise-li…

上記は、Node.js でブレークポイント再開を実装する方法の詳細です。Node.js でのブレークポイント再開の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Node.js をベースに大きなファイルを分割してアップロードする例
  • Node.jsにおけるファイルブレークポイント再開の原理と方法のまとめ
  • Node.js でのブレークポイント再開の実装
  • React+Nodeは、大きなファイルを分割してアップロードし、数秒でアップロードを再開するというアイデアを実現します。

<<:  MySQL 8.0.15 のインストールと設定方法のグラフィックチュートリアル (Win10 Home バージョン 64)

>>:  Centos での Python のアップグレードと Mongodb ドライバーのインストールに関する問題

推薦する

VMware+centOS 8 で http プロトコルに基づく Git サービスを構築する方法

目次1. 原因2. デバイス情報3. 準備4. Apacheをインストールする5. gitを設定する...

HTMLページがincludeを使用してphpファイルをインポートした後に余分な空白行があります

インターネットで見つけた方法は効果的ですinclude によって導入されたフッター ファイルとヘッダ...

CentOS 7.4 にソースコードから MySQL 8.0 をインストールするための詳細なチュートリアル

目次1. 環境2. 準備3. MySQL 8.0.11をインストールするMySQL 8 の公式バージ...

Ubuntu16.04にCUDA9.0をインストールするための詳細なチュートリアル

序文:この記事は、CUDA 9.0 をインストールした経験に基づいています。CUDA 9.0 は現在...

HTML ページでコンテンツの選択、コピー、右クリックを防止する方法の詳細な説明

時には、Web ページに掲載されているコンテンツが悪意のある人物に盗用されるのを望まないため、Web...

MySQL のスローログオンラインの問題と最適化ソリューション

MySQL スロー ログは、MySQL DBA やその他の開発および運用担当者が細心の注意を払う必要...

nginx+uwsgi で Django プロジェクトを開始するための詳細な手順

Django で Web プロジェクトを開発する場合、開発およびテストのプロセスでは Django ...

Vueのキーボードイベントの詳細な説明

目次共通キーエイリアスエイリアスが指定されていないキーシステム修飾キーカスタムキーエイリアス要約する...

MySQL で数千万のテストデータを含むテストデータベースを作成する方法

場合によっては、MySQL が公式に提供しているテスト ライブラリに基づいてテスト データを作成し、...

mysql 8.0.16 winx64.zip インストールと設定方法のグラフィックチュートリアル

この記事では、MySQL 8.0.16 winx64.zipのインストールと設定方法の具体的なコード...

JavaScriptはスタック構造の詳細なプロセスを実装する

目次1. スタック構造を理解する2. スタック構造のカプセル化3. 10進数を2進数に変換する1. ...

Windows で MySQL データベースを別のディスクに移動する

序文今日、MySQL をインストールしたところ、データベース ストレージがデフォルトで C ドライブ...

Reactは一般的なスケルトン画面コンポーネントの例を実装します

目次スケルトンスクリーンとは何ですか?デモデザインのアイデア具体的な実装スケルトンスクリーンとは何で...

Vue での keepAlive の使用例の詳細な説明

開発においては、一覧から詳細ページにジャンプし、また詳細ページに戻る際に一覧ページの状態(スクロール...

Vue が学ぶべき知識ポイント: forEach() の使用

序文フロントエンド開発では、目的のコンテンツを取得するためにループをトラバースする必要がある状況に頻...