亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Node中怎么利用WebSocket實現多文件下載功能

發布時間:2021-07-21 11:10:47 來源:億速云 閱讀:538 作者:Leah 欄目:web開發

這篇文章將為大家詳細講解有關Node中怎么利用WebSocket實現多文件下載功能,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

列表

Node中怎么利用WebSocket實現多文件下載功能

下載列表

Node中怎么利用WebSocket實現多文件下載功能

本文地址倉庫:https://github.com/Rynxiao/yh-tools,如果喜歡,歡迎star.

涉及技術

  • Express 后端服務

  • Webpack 模塊化編譯工具

  • Nginx 主要做文件gzip壓縮(發現Express添加gzip有點問題,才棄坑nginx)

  • Ant-design 前端UI庫

  • React + React Router

  • WebSocket 進度回傳服務

其中還有點小插曲,最開始是使用docker起了一個nginx服務,但是發現內部轉發一直有問題,同時獲取宿主主機IP也出現了點問題,然后折磨了好久放棄了。(docker研究不深,敬請諒解^_^)

下載部分細節

Node中怎么利用WebSocket實現多文件下載功能

首先瀏覽器會連接WebSocket服務器,同時在WebSocket服務器上存在一個所有客戶端的Map,瀏覽器端生成一個uuid作為瀏覽器客戶端id,然后將這個鏈接作為值存進Map中。

客戶端:

// list.jsx
await WebSocketClient.connect((event) => {
 const data = JSON.parse(event.data);
 if (data.event === 'close') {
  this.updateCloseStatusOfProgressBar(list, data);
 } else {
  this.generateProgressBarList(list, data);
 }
});
// src/utils/websocket.client.js
async connect(onmessage, onerror) {
 const socket = this.getSocket();
 return new Promise((resolve) => {
  // ...
 });
}
getSocket() {
 if (!this.socket) {
  this.socket = new WebSocket(
   `ws://localhost:${CONFIG.PORT}?from=client&id=${clientId}`,
   'echo-protocol',
  );
 }
 return this.socket;
}

服務端:

// public/javascript/websocket/websocket.server.js
connectToServer(httpServer) {
 initWsServer(httpServer);
 wsServer.on('request', (request) => {
  // uri: ws://localhost:8888?from=client&id=xxxx-xxxx-xxxx-xxxx
  logger.info('[ws server] request');
  const connection = request.accept('echo-protocol', request.origin);
  const queryStrings = querystring.parse(request.resource.replace(/(^\/|\?)/g, ''));
  
  // 每有連接連到websocket服務器,就將當前連接保存到map中
  setConnectionToMap(connection, queryStrings);
  connection.on('message', onMessage);
  connection.on('close', (reasonCode, description) => {
   logger.info(`[ws server] connection closed ${reasonCode} ${description}`);
  });
 });

 wsServer.on('close', (connection, reason, description) => {
  logger.info('[ws server] some connection disconnect.');
  logger.info(reason, description);
 });
}

然后在瀏覽器端點擊下載的時候,會傳遞兩個主要的字段resourceId(在代碼中由parentId和childId組成)和客戶端生成的bClientId。這兩個id有什么用呢?

每次點擊下載,都會在Web服務器中生成一個WebSocket的客戶端,那么這個resouceId就是作為在服務器中生成的WebSocket服務器的key值。

bClientId主要是為了區分瀏覽器的客戶端,因為考慮到同時可能會有多個瀏覽器接入,這樣在WebSocket服務器中產生消息的時候,就可以用這個id來區分應該發送給哪個瀏覽器客戶端

客戶端:

// list.jsx
http.get(
 'download',
 {
  code,
  filename,
  parent_id: row.id,
  child_id: childId,
  download_url: url,
  client_id: clientId,
 },
);
// routes/api.js
router.get('/download', async (req, res) => {
 const { code, filename } = req.query;
 const url = req.query.download_url;
 const clientId = req.query.client_id;
 const parentId = req.query.parent_id;
 const childId = req.query.child_id;
 const connectionId = `${parentId}-${childId}`;
 const params = {
  code,
  url,
  filename,
  parent_id: parentId,
  child_id: childId,
  client_id: clientId,
 };
 const flag = await AnnieDownloader.download(connectionId, params);
 if (flag) {
  await res.json({ code: 200 });
 } else {
  await res.json({ code: 500, msg: 'download error' });
 }
});
// public/javascript/annie.js
async download(connectionId, params) {
  //...
 // 當annie下載時,會進行數據監聽,這里會用到節流,防止進度回傳太快,websocket服務器無法反應
 downloadProcess.stdout.on('data', throttle((chunk) => {
  try {
   if (!chunk) {
    isDownloading = false;
   }
   // 這里主要做的是解析數據,然后發送進度和速度等信息給websocket服務器
   getDownloadInfo(chunk, ws, params);
  } catch (e) {
   downloadSuccess = false;
   WsClient.close(params.client_id, connectionId, 'download error');
   this.stop(connectionId);
   logger.error(`[server annie download] error: ${e}`);
  }
 }, 500, 300));
}

服務端收到進度以及速度的消息后,回傳給客戶端,如果進度達到了100%,那么就刪除掉存在server中的服務器中起的websocket的客戶端,并且發送一個客戶端被關閉的通知,通知瀏覽器已經下載完成。

// public/javascript/websocket/websocket.server.js
function onMessage(message) {
 const data = JSON.parse(message.utf8Data);
 const id = data.client_id;
 if (data.event === 'close') {
  logger.info('[ws server] close event');
  closeConnection(id, data);
 } else {
  getConnectionAndSendProgressToClient(data, id);
 }
}
function getConnectionAndSendProgressToClient(data, clientId) {
 const browserClient = clientsMap.get(clientId);
 // logger.info(`[ws server] send ${JSON.stringify(data)} to client ${clientId}`);
 if (browserClient) {
  const serverClientId = `${data.parent_id}-${data.child_id}`;
  const serverClient = clientsMap.get(serverClientId);
  // 發送從web服務器中傳過來的進度、速度給瀏覽器
  browserClient.send(JSON.stringify(data));
  // 如果進度已經達到了100%
  if (data.progress >= 100) {
   logger.info(`[ws server] file has been download successfully, progress is ${data.progress}`);
   logger.info(`[ws server] server client ${serverClientId} ready to disconnect`);
   // 從clientsMap將當前的這個由web服務器創建的websocket客戶端移除
   // 然后關閉當前連接
   // 同時發送下載完成的消息給瀏覽器
   clientsMap.delete(serverClientId);
   serverClient.send(JSON.stringify({ connectionId: serverClientId, event: 'complete' }));
   serverClient.close('download completed');
  }
 }
}

關于Node中怎么利用WebSocket實現多文件下載功能就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

浠水县| 银川市| 铁力市| 阳泉市| 白水县| 武宁县| 同心县| 万山特区| 玉龙| 尼木县| 永兴县| 霍山县| 宁海县| 塔城市| 云安县| 江门市| 游戏| 民权县| 满洲里市| 瑞丽市| 鄂伦春自治旗| 萨嘎县| 太仆寺旗| 衡东县| 富顺县| 闻喜县| 长兴县| 湛江市| 江口县| 个旧市| 特克斯县| 庄浪县| 安新县| 铜山县| 南靖县| 安乡县| 荣成市| 通榆县| 庐江县| 邮箱| 内黄县|