node.js使用url下载文件

来源:互联网 发布:java三维地质建模 编辑:程序博客网 时间:2024/06/16 21:56

采用http协议来实现文件下载。其优点在于不需要以来额外程序来下载文件

[javascript] view plain copy
  1. // Dependencies  
  2. var fs = require('fs');  
  3. var url = require('url');  
  4. var http = require('http');  
  5. var exec = require('child_process').exec;  
  6. var spawn = require('child_process').spawn;  
  7.   
  8. // App variables  
  9. var file_url = 'http://www.sina.com/tmp.jpg';  
  10. var DOWNLOAD_DIR = './downloads/';  
  11.   
  12. // We will be downloading the files to a directory, so make sure it's there  
  13. // This step is not required if you have manually created the directory  
  14. var mkdir = 'mkdir -p ' + DOWNLOAD_DIR;  
  15. var child = exec(mkdir, function(err, stdout, stderr) {  
  16.     if (err) throw err;  
  17.     else download_file_httpget(file_url);  
  18. });  
  19.   
  20. // Function to download file using HTTP.get  
  21. var download_file_httpget = function(file_url) {  
  22. var options = {  
  23.     host: url.parse(file_url).host,  
  24.     port: 80,  
  25.     path: url.parse(file_url).pathname  
  26. };  
  27.   
  28. var file_name = url.parse(file_url).pathname.split('/').pop();  
  29. var file = fs.createWriteStream(DOWNLOAD_DIR + file_name);  
  30.   
  31. http.get(options, function(res) {  
  32.     res.on('data'function(data) {  
  33.             file.write(data);  
  34.         }).on('end'function() {  
  35.             file.end();  
  36.             console.log(file_name + ' downloaded to ' + DOWNLOAD_DIR);  
  37.         });  
  38.     });  
  39. };  

使用curl来下载文件,我们需要采用child_process模块中的spawn方法。

[javascript] view plain copy
  1. // Function to download file using curl  
  2. var download_file_curl = function(file_url) {  
  3.   
  4.     // extract the file name  
  5.     var file_name = url.parse(file_url).pathname.split('/').pop();  
  6.     // create an instance of writable stream  
  7.     var file = fs.createWriteStream(DOWNLOAD_DIR + file_name);  
  8.     // execute curl using child_process' spawn function  
  9.     var curl = spawn('curl', [file_url]);  
  10.     // add a 'data' event listener for the spawn instance  
  11.     curl.stdout.on('data'function(data) { file.write(data); });  
  12.     // add an 'end' event listener to close the writeable stream  
  13.     curl.stdout.on('end'function(data) {  
  14.         file.end();  
  15.         console.log(file_name + ' downloaded to ' + DOWNLOAD_DIR);  
  16.     });  
  17.     // when the spawn child process exits, check if there were any errors and close the writeable stream  
  18.     curl.on('exit'function(code) {  
  19.         if (code != 0) {  
  20.             console.log('Failed: ' + code);  
  21.         }  
  22.     });  
  23. };  

另外的方法是使用wget,这种方法的代码非常简洁。

[javascript] view plain copy
  1. // Function to download file using wget  
  2. var download_file_wget = function(file_url) {  
  3.   
  4.     // extract the file name  
  5.     var file_name = url.parse(file_url).pathname.split('/').pop();  
  6.     // compose the wget command  
  7.     var wget = 'wget -P ' + DOWNLOAD_DIR + ' ' + file_url;  
  8.     // excute wget using child_process' exec function  
  9.   
  10.     var child = exec(wget, function(err, stdout, stderr) {  
  11.         if (err) throw err;  
  12.         else console.log(file_name + ' downloaded to ' + DOWNLOAD_DIR);  
  13.     });  
  14. };  

关于child_process.spawnchild_process.exec最大的不同之处在于返回值: spawn returns a stream and exec returns a buffer.

child_process.spawn returns an object with stdout and stderr streams. You can tap on thestdout stream to read data that the child process sends back to Node. stdout being a stream has the "data", "end", and other events that streams have. spawn is best used to when you want the child process to return a large amount of data to Node - image processing, reading binary data etc.

child_process.spawn is "asynchronously asynchronous", meaning it starts sending back data from the child process in a stream as soon as the child process starts executing.

child_process.exec returns the whole buffer output from the child process. By default the buffer size is set at 200k. If the child process returns anything more than that, you program will crash with the error message "Error: maxBuffer exceeded". You can fix that problem by setting a bigger buffer size in the exec options. But you should not do it because exec is not meant for processes that return HUGE buffers to Node. You should use spawn for that. So what do you use exec for? Use it to run programs that return result statuses, instead of data.

child_process.exec is "synchronously asynchronous", meaning although the exec is asynchronous, it waits for the child process to end and tries to return all the buffered data at once. If the buffer size of exec is not set big enough, it fails with a "maxBuffer exceeded" error.

另外,node作为server可以实现upload以及download功能。

如下的code是download的功能。

[javascript] view plain copy
  1. app.get('/upload/:fileid'function(req, res){  
  2.      gfs.getGridFile(req.params.fileid, function(err, file){  
  3.          res.header('Content-Type', file.contentType);  
  4.         res.header('Content-Disposition''attachment; filename='+file.filename);  
  5.         return file.stream(true).pipe(res);  
  6.     });  
  7. });  

Code的下载功能在于header中的attachement选项。

如下的code是upload功能。 Upload的文件在req.files中体现。

对于上传的文件,一种方法是保存在server的指定目录下,另外一种方法是保存在MongoDB中。

[javascript] view plain copy
  1.     app.post('/upload/create'function(req, res){  
  2.         //1. save the upload file to folder public/doc/  
  3. //      var tmppath = req.files.file.path;  
  4. //      var targetpath = /public/doc/'+req.files.file.name;  
  5. //  
  6. //      fs.rename(tmppath, targetpath, function(err){  
  7. //          if (err) throw err;  
  8. //  
  9. //          fs.unlink(tmppath, function(){  
  10. //              if (err) throw err;  
  11. //  
  12. //              //res.send({filename: req.files.file.name});  
  13. //          });  
  14. //      });  
  15.   
  16.         //2. save the upload file to mongoDB GridFile.  
  17.         var opts = {content_type: req.files.file.type};  
  18.   
  19.         gfs.putGridFileByPath(req.files.file.path, req.files.file.name, opts, function(err, result){