一、準備工作

在開始編碼之前,讓我們先確保您的開發(fā)環(huán)境已經(jīng)準備就緒。您需要安裝Node.js和npm(Node.js包管理工具)。你可以從Node.js官網(wǎng)下載最新版本的Node.js,安裝過程非常簡單。安裝完成后,您就可以開始編寫代碼了。

二、實現(xiàn)文件下載功能

首先,我們需要創(chuàng)建一個簡單的Node.js服務器,用于處理文件下載請求。您可以使用內置的http模塊或流行的Express.js框架來實現(xiàn)。在這個例子中,我們將使用http模塊:

const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
  if (req.url === '/download') {
    const filePath = path.join(__dirname, 'example.zip');
    const fileSize = fs.statSync(filePath).size;

    res.setHeader('Content-Type', 'application/octet-stream');
    res.setHeader('Content-Disposition', 'attachment; filename="example.zip"');
    res.setHeader('Content-Length', fileSize);

    const readStream = fs.createReadStream(filePath);
    readStream.pipe(res);
  } else {
    res.statusCode = 404;
    res.end('Not found');
  }
});

server.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

在上述代碼中,我們創(chuàng)建了一個簡單的HTTP服務器,當客戶端訪問/download路徑時,服務器會讀取本地的example.zip文件并將其傳輸給客戶端。我們設置了適當?shù)腍TTP頭部信息,如Content-Type、Content-Disposition和Content-Length,以確保文件下載正常進行。

三、實現(xiàn)下載進度條

現(xiàn)在,我們來實現(xiàn)文件下載進度條。我們將使用Node.js的內置fs模塊來監(jiān)控文件讀取的進度,并將其發(fā)送給客戶端。首先,我們需要修改之前的服務器代碼:

const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
  if (req.url === '/download') {
    const filePath = path.join(__dirname, 'example.zip');
    const fileSize = fs.statSync(filePath).size;

    res.setHeader('Content-Type', 'application/octet-stream');
    res.setHeader('Content-Disposition', 'attachment; filename="example.zip"');
    res.setHeader('Content-Length', fileSize);

    let totalBytes = 0;
    const readStream = fs.createReadStream(filePath);
    readStream.on('data', (chunk) => {
      totalBytes += chunk.length;
      const progress = Math.round((totalBytes / fileSize) * 100);
      res.write(`${progress}%\n`);
    });
    readStream.pipe(res);
  } else {
    res.statusCode = 404;
    res.end('Not found');
  }
});

server.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

在這個版本中,我們在readStream的 'data' 事件中計算下載進度,并將進度信息寫入響應對象。這樣,當客戶端接收到響應時,就可以看到實時的下載進度。

四、客戶端實現(xiàn)

現(xiàn)在,讓我們在客戶端實現(xiàn)文件下載進度條。我們可以使用JavaScript的Fetch API或XMLHttpRequest對象來發(fā)送下載請求,并在UI上顯示進度信息。以下是一個使用Fetch API的示例:

<!DOCTYPE html>
<html>
<head>
  <title>File Download Progress</title>
</head>
<body>
  Downloading File...
  <progress id="progress-bar" value="0" max="100" style="width: 100%;"></progress>
  <script>
    fetch('/download')
      .then(response => {
        const totalSize = response.headers.get('Content-Length');
        const progressBar = document.getElementById('progress-bar');
        let downloaded = 0;

        const reader = response.body.getReader();
        return reader.read().then(function processResults({ done, value }) {
          if (done) {
            return;
          }

          downloaded += value.length;
          const progress = Math.round((downloaded / totalSize) * 100);
          progressBar.value = progress;

          return reader.read().then(processResults);
        });
      })
      .catch(error => {
        console.error('Error downloading file:', error);
      });
  </script>
</body>
</html>

在這個示例中,我們使用Fetch API發(fā)送下載請求,并在響應頭中獲取文件大小信息。然后,我們使用響應對象的body屬性的getReader()方法來讀取數(shù)據(jù)塊,并根據(jù)已下載的數(shù)據(jù)量更新進度條的值。

五、錯誤處理

在實際應用中,我們需要考慮各種錯誤情況,并為用戶提供友好的錯誤提示。例如,如果文件不存在或下載過程中出現(xiàn)網(wǎng)絡錯誤,我們應該捕獲這些異常并做出相應的處理。以下是一個修改后的服務器代碼,演示了如何處理錯誤:

const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
  if (req.url === '/download') {
    const filePath = path.join(__dirname, 'example.zip');

    fs.stat(filePath, (err, stats) => {
      if (err) {
        res.statusCode = 404;
        res.end('File not found');
        return;
      }

      res.setHeader('Content-Type', 'application/octet-stream');
      res.setHeader('Content-Disposition', 'attachment; filename="example.zip"');
      res.setHeader('Content-Length', stats.size);

      let totalBytes = 0;
      const readStream = fs.createReadStream(filePath);
      readStream.on('data', (chunk) => {
        totalBytes += chunk.length;
        const progress = Math.round((totalBytes / stats.size) * 100);
        res.write(`${progress}%\n`);
      });

      readStream.on('error', (err) => {
        res.statusCode = 500;
        res.end('Error downloading file');
      });

      readStream.pipe(res);
    });
  } else {
    res.statusCode = 404;
    res.end('Not found');
  }
});

server.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

在這個版本中,我們使用fs.stat()方法檢查文件是否存在,如果不存在,則返回404錯誤。同時,我們還添加了readStream的'error'事件處理程序,用于處理下載過程中可能出現(xiàn)的其他錯誤。

六、總結

通過本文,您已經(jīng)了解了如何使用Node.js實現(xiàn)文件下載進度條功能。我們從簡單的文件下載開始,逐步添加進度條顯示和錯誤處理等功能,最終構建出一個完整的文件下載解決方案。這種技術不僅可以應用于web應用程序,也可以用于構建各種需要文件下載功能的桌面應用程序或移動應用程序。希望本文對您有所幫助,祝您編碼愉快!