在NodeJS中下载大文件的方法是什么?

问题描述:

以下服务器代码对于5GB文件使用 wget http://localhost:11146/base/bigFile.zip正常工作,但未使用客户端代码。在NodeJS中下载大文件的方法是什么?

服务器端代码。

var http = require("http"); 
var fs = require("fs"); 
var filename = "base/bigFile.zip"; 

var serv = http.createServer(function (req, res) { 
    var stat = fs.statSync(filename); 
    res.writeHeader(200, {"Content-Length": stat.size}); 
    var fReadStream = fs.createReadStream(filename); 
    fReadStream.on('data', function (chunk) { 
     if(!res.write(chunk)){ 
      fReadStream.pause(); 
     } 
    }); 
    fReadStream.on('end', function() { 
     res.end(); 
    }); 
    res.on("drain", function() { 
     fReadStream.resume(); 
    }); 
}); 

serv.listen(1114); 
使用请求模块

客户端代码。这段代码有什么问题?

var request = require('request') 
request('http:/localhost:11146/base/bigFile.zip', function (error, response, body) { 
    console.log('error:', error); // Print the error if one occurred 
    console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received 
    console.log('body:', body); // Print the HTML for the Google homepage. 
}); 

误差为上述客户端代码低于 -

error: Error: Invalid protocol 
    at Request.init (/Users/air/Projects/node_modules/request/request.js:338:51) 
    at new Request (/Users/air/Projects//node_modules/request/request.js:105:8) 
    at request (/Users/air/Projects/Vertico/Vertico-CLI/node_modules/request/index.js:53:11) 
    at Object.<anonymous> (/Users/air/Projects/req.js:2:1) 
    at Module._compile (module.js:569:30) 
    at Object.Module._extensions..js (module.js:580:10) 
    at Module.load (module.js:503:32) 
    at tryModuleLoad (module.js:466:12) 
    at Function.Module._load (module.js:458:3) 
    at Function.Module.runMain (module.js:605:10) 
statusCode: undefined 
body: undefined 

我修改客户端使用wget壳进程,而不是请求包,该代码是下面,问题是 - 我无法看到wget的良好下载进度,任何解决此代码的方法,以便我可以在子进程中看到进度条。

const fs = require('fs'); 
    const child_process = require('child_process'); 

    var workerProcess = child_process.spawn('wget', ['-O','fdsf.zip', 'http://localhost:11146/base/bigFile.zip']); 

    workerProcess.stdout.on('data', function (data) { 
    console.log('stdout: ' + data); 
    }); 

    workerProcess.stderr.on('data', function (data) { 
    //console.log('stderr: ' + data); 
    }); 

    workerProcess.on('close', function (code) { 
     console.log('Download Completed' + code); 
    }); 

所以最后我想知道如何使用被写入的NodeJS客户端代码下载文件?

最简单的方法是使用request模块

在这里,你试图在内存中存储整个结果和控制台日志它。 5GB非常大,要么增加Node.js内存限制(不推荐),要么必须使用流。见streaming example下面从request NPM文件:

const fs = require('fs'); 
const request = require('request'); 
request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png')) 

必须通过管道的响应,使无论是1MB或1GB或者1TB,只有文件的一小部分会在内存中,它会被写入到磁盘尽快。你可以使用相同的方法使用Node.js内置的函数,但是实现将很困难,并且像request模块在那里时重新发明*一样。

对于下载与进步可以使用request-progress模块request模块一起,见下面的例子(taken from their documentation):

var fs = require('fs'); 
var request = require('request'); 
var progress = require('request-progress'); 

// The options argument is optional so you can omit it 
progress(request('https://az412801.vo.msecnd.net/vhd/VMBuild_20141027/VirtualBox/IE11/Windows/IE11.Win8.1.For.Windows.VirtualBox.zip'), { 
    // throttle: 2000,     // Throttle the progress event to 2000ms, defaults to 1000ms 
    // delay: 1000,      // Only start to emit after 1000ms delay, defaults to 0ms 
    // lengthHeader: 'x-transfer-length' // Length header to use, defaults to content-length 
}) 
.on('progress', function (state) { 
    // The state is an object that looks like this: 
    // { 
    //  percent: 0.5,    // Overall percent (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) 
    //  } 
    // } 
    console.log('progress', state); 
}) 
.on('error', function (err) { 
    // Do something with err 
}) 
.on('end', function() { 
    // Do something after request finishes 
}) 
.pipe(fs.createWriteStream('IE11.Win8.1.For.Windows.VirtualBox.zip')); 
+1

谢谢。任何提示如何捕捉进展? – irobo

+2

我猜你必须在写入文件和使用来自响应标头的内容长度和每个事件期间收到的字节进行计算之间进行点击。有可能是模块,如果我碰到一个,会让你知道 –

+2

@ user2979152看到这个问题:https:// *。com/questions/18323152/get-download-progress-in-node-js -with-request与进度下载 –

var request = require('request') 
request('http:/localhost:11146/base/bigFile.zip', function (error, response, body) { 
    console.log('error:', error); // Print the error if one occurred 
    console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received 
    console.log('body:', body); // Print the HTML for the Google homepage. 
}); 

应该是http://localhost:11146/base/bigFile.zip代替http:/localhost:11146/base/bigFile.zip

我代码版本。

var fs = require('fs'); 
var request = require('request'); 
var progress = require('request-progress'); 
var url = 'http://localhost:4181'; 
var filename = 's.zip'; 
var pre = '----'; 

downloadManager = function(url,filename){ 
    progress(request(url), { 
    throttle:500 
    }) .on('progress', function (state) { 
     process.stdout.write(pre+''+ (Math.round(state.percent*100))+"%"); 
    }) 
    .on('error', function (err) { 
     console.log('error :('+err); 
    }) 
    .on('end', function() { 
     console.log(pre+'100% \n Download Completed'); 
    }) 
    .pipe(fs.createWriteStream(filename)); 
}; 


downloadManager(url,filename); 
+0

很简单的代码。 – irobo