【问题标题】:Get download progress in Node.js with request通过请求在 Node.js 中获取下载进度
【发布时间】:2013-08-21 19:14:43
【问题描述】:

我正在创建一个使用 Node 模块 request 下载应用程序文件的更新程序。如何使用chunk.length 估算剩余文件大小?这是我的部分代码:

var file_url = 'http://foo.com/bar.zip';
var out = fs.createWriteStream('baz.zip');

var req = request({
    method: 'GET',
    uri: file_url
});

req.pipe(out);

req.on('data', function (chunk) {
    console.log(chunk.length);
});

req.on('end', function() {
    //Do something
});

【问题讨论】:

  • 我有里面的 .zip : node-webkit.app / 当我提取数据时-> 不能再运行 .app: / 我的代码:: fs.writeFileSync(frameZipFilePath, data, "binary ");var zip = new AdmZip(frameZipFilePath); zip.extractAllTo(path.resolve("", "tmp"), true);

标签: node.js download request progress


【解决方案1】:

这应该可以得到你想要的总数:

req.on( 'response', function ( data ) {
    console.log( data.headers[ 'content-length' ] );
} );

我得到9404541的内容长度

【讨论】:

  • 谢谢!这个长度是字节吗?
  • 是的。它是 i 字节。
【解决方案2】:
function download(url, callback, encoding){
        var request = http.get(url, function(response) {
            if (encoding){
                response.setEncoding(encoding);
            }
            var len = parseInt(response.headers['content-length'], 10);
            var body = "";
            var cur = 0;
            var obj = document.getElementById('js-progress');
            var total = len / 1048576; //1048576 - bytes in  1Megabyte

            response.on("data", function(chunk) {
                body += chunk;
                cur += chunk.length;
                obj.innerHTML = "Downloading " + (100.0 * cur / len).toFixed(2) + "% " + (cur / 1048576).toFixed(2) + " mb\r" + ".<br/> Total size: " + total.toFixed(2) + " mb";
            });

            response.on("end", function() {
                callback(body);
                obj.innerHTML = "Downloading complete";
            });

            request.on("error", function(e){
                console.log("Error: " + e.message);
            });

        });
    };

【讨论】:

  • 1048576 来自哪里?这是一个宇宙常数吗?
  • 但是对于分块响应,即包含多个块的大流会跳过内容长度标头。那我们该怎么办?
  • 1048576 是 1024 的平方
  • 一兆字节的字节数
【解决方案3】:

我写了一个模块来做你想做的事:status-bar

var bar = statusBar.create ({ total: res.headers["content-length"] })
    .on ("render", function (stats){
      websockets.send (stats);
    })

req.pipe (bar);

【讨论】:

  • 是的,最初我使用的是您的模块,但我希望能够使用 websockets 在 GUI 中向用户显示进度条。
  • 你可以这样做。当调用渲染函数时,向客户端发送状态栏。它是一个字符串,你可以用它做任何事情。
  • 是的,但在某些时候,自己编写一些东西比解析另一个模块的字符串更容易。 :) 不过,感谢您的提示。
  • 我在 4 天前更新了模块。现在它不返回字符串,它返回原始数据,因此您可以在服务器或客户端中呈现状态栏。我已经编辑了答案。
  • 那些看起来很棒的更新!我喜欢它是多么有据可查。我一定会考虑它以备将来使用。
【解决方案4】:

使用酷炫的 node-request-progress 模块,你可以在 es2015 中做这样的事情:

import { createWriteStream } from 'fs'
import request from 'request'
import progress from 'request-progress'

progress(request('http://foo.com/bar.zip'))
 .on('progress', state => {

   console.log(state)

   /*
   {
       percentage: 0.5,        // Overall percentage (between 0 to 1)
       speed: 554732,          // The download speed in bytes/sec
       size: {
         total: 90044871,      // The total payload size in bytes
         transferred: 27610959 // The transferred payload size in bytes
       },
       time: {
         elapsed: 36.235,      // The total elapsed seconds since the start (3 decimals)
         remaining: 81.403     // The remaining seconds to finish (3 decimals)
       }
   }
   */

  })
  .on('error', err => console.log(err))
  .on('end', () => {})
  .pipe(createWriteStream('bar.zip'))

【讨论】:

    【解决方案5】:

    如果有人想知道进度而不使用其他库而只请求,那么您可以使用以下方法:

    function downloadFile(file_url , targetPath){
        // Save variable to know progress
        var received_bytes = 0;
        var total_bytes = 0;
    
        var req = request({
            method: 'GET',
            uri: file_url
        });
    
        var out = fs.createWriteStream(targetPath);
        req.pipe(out);
    
        req.on('response', function ( data ) {
            // Change the total bytes value to get progress later.
            total_bytes = parseInt(data.headers['content-length' ]);
        });
    
        req.on('data', function(chunk) {
            // Update the received bytes
            received_bytes += chunk.length;
    
            showProgress(received_bytes, total_bytes);
        });
    
        req.on('end', function() {
            alert("File succesfully downloaded");
        });
    }
    
    function showProgress(received,total){
        var percentage = (received * 100) / total;
        console.log(percentage + "% | " + received + " bytes out of " + total + " bytes.");
        // 50% | 50000 bytes received out of 100000 bytes.
    }
    
    downloadFile("https://static.pexels.com/photos/36487/above-adventure-aerial-air.jpg","c:/path/to/local-image.jpg");
    

    received_bytes 变量保存每个发送的块长度的总和,并根据total_bytes 检索进度。

    【讨论】:

      【解决方案6】:

      如果你正在使用“请求”模块,并且想在不使用任何额外模块的情况下显示下载百分比,可以使用以下代码:

      function getInstallerFile (installerfileURL,installerfilename) {
      
          // Variable to save downloading progress
          var received_bytes = 0;
          var total_bytes = 0;
      
          var outStream = fs.createWriteStream(installerfilename);
          
          request
              .get(installerfileURL)
                  .on('error', function(err) {
                      console.log(err);
                  })
                  .on('response', function(data) {
                      total_bytes = parseInt(data.headers['content-length']);
                  })
                  .on('data', function(chunk) {
                      received_bytes += chunk.length;
                      showDownloadingProgress(received_bytes, total_bytes);
                  })
                  .pipe(outStream);
      };
      
      function showDownloadingProgress(received, total) {
          var platform = "win32"; // Form windows system use win32 for else leave it empty
          var percentage = ((received * 100) / total).toFixed(2);
          process.stdout.write((platform == 'win32') ? "\033[0G": "\r");
          process.stdout.write(percentage + "% | " + received + " bytes downloaded out of " + total + " bytes.");
      }
      

      用法:

      getInstallerFile("http://example.com/bar.zip","bar.zip");
      

      【讨论】:

      • 完美工作只需要声明平台变量和INSTALLER_FILE到文件名保存
      猜你喜欢
      • 1970-01-01
      • 2018-10-31
      • 2016-10-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-15
      • 2016-03-01
      • 2016-05-14
      • 1970-01-01
      相关资源
      最近更新 更多