nodejs ssh2基本功能封装,实现上传、下载文件以及文件夹

最新封装见:http://blog.csdn.net/llmys/article/details/52997924

最近在做自动化测试的时候,需要用到nodejs ssh2模块将windows上的文件传到linux机器上,由于网上别人封装的ssh2-util模块实在不好用,不是下载文件夹之后无法退出,就是下载不下来。可能是我自己用法不对的缘故,由于我没有学过JS,很多不懂,所有用ssh2更加不好用,每次我都想说一句:"好恼火"。

好了,吐槽完毕,接下来写写我封装的基本功能。仅仅实现了运行linux的shell命令、上传文件、下载文件、上传文件夹、下载文件夹。

上传文件夹思路:首先获取本地机器文件目录下的子目录列表以及文件名列表,再通过调用shell函数执行mkdir命令在linux机器上面创建文件夹,然后再一个一个的上传文件。

下载文件夹思路:首先获取远程linux机器目录下的子目录列表以及文件名列表,再在本地机器上创建文件夹,再将文件一个一个的下载下来。

也许是我没有学过JS、Node.js的缘故,每次用同一个连接下来多个文件就会出问题,并发多了就出现问题了,希望会的人可以给我指点一下思路,或者给我说一下应该怎么使用。所有在我的代码中我都是等待ssh的操作一个一个的完成之后再去执行其他操作。

"use strict"
var ssh2 = require("ssh2");
var util=require("util")
var events=require("events");
var Client = require("ssh2").Client;
var fs = require("fs");
var path = require('path');
var async = require('async');


/**
* 描述:连接远程电脑
* 参数:server 远程电脑凭证;then 回调函数
* 回调:then(conn) 连接远程的client对象
*/
function Connect(server, then){
	var conn = new Client();
	conn.on("ready", function(){
		then(conn);
	}).on('error', function(err){
		//console.log("connect error!");
	}).on('end', function() {
		//console.log("connect end!");
	}).on('close', function(had_error){
		//console.log("connect close");
	}).connect(server);
}

/**
* 描述:运行shell命令
* 参数:server 远程电脑凭证;cmd 执行的命令;then 回调函数
* 回调:then(err, data) : data 运行命令之后的返回数据信息
*/
function Shell(server, cmd, then){
	Connect(server, function(conn){
		conn.shell(function(err, stream){
			if(err){
				then(err);
			}else{// end of if
				var buf = "";
				stream.on('close', function(){						
					conn.end();						
					then(err, buf);
				}).on('data', function(data){
					buf=buf+data;					
				}).stderr.on('data', function(data) {
					console.log('stderr: ' + data);
				});	
				stream.end(cmd);		
			}							
		});
	});	
}

/**
* 描述:上传文件
* 参数:server 远程电脑凭证;localPath 本地路径;remotePath 远程路径;then 回调函数
* 回调:then(err, result)
*/
function UploadFile(server, localPath, remotePath , then){
	Connect(server, function(conn){
		conn.sftp(function(err, sftp){
			if(err){
				then(err);
			}else{
				sftp.fastPut(localPath, remotePath, function(err, result){
					conn.end();
					then(err, result);
				});
			}
		});
	});
}

/**
* 描述:下载文件
* 参数:server 远程电脑凭证;remotePath 远程路径;localPath 本地路径;then 回调函数
* 回调:then(err, result)
*/
function DownloadFile(server, remotePath, localPath, then){
	Connect(server, function(conn){
		conn.sftp(function(err, sftp){
			if(err){
				then(err);
			}else{
				sftp.fastGet(remotePath, localPath, function(err, result){
					if(err){
						then(err);
					}else{
						conn.end();
						then(err, result);
					}
				});
			}
		});
	});
}

/**
* 描述:获取远程文件路径下文件列表信息
* 参数:server 远程电脑凭证;
*		remotePath 远程路径;
*		isFile 是否是获取文件,true获取文件信息,false获取目录信息;
*		then 回调函数
* 回调:then(err, dirs) : dir, 获取的列表信息
*/
function GetFileOrDirList(server, remotePath, isFile, then){
	var cmd = "find " + remotePath + " -type "+ (isFile == true ? "f":"d") + "\r\nexit\r\n";	
	Shell(server, cmd, function(err, data){
		var arr = [];
		var remoteFile = [];
		arr = data.split("\r\n");
		arr.forEach(function(dir){
			if(dir.indexOf(remotePath) ==0){
				remoteFile.push(dir);
			}
		});
		then(err, remoteFile);
	});
}

/**
* 描述:控制上传或者下载一个一个的执行
*/
function Control(){
	events.EventEmitter.call(this);
}
util.inherits(Control, events.EventEmitter); // 使这个类继承EventEmitter

var control = new Control();

control.on("donext", function(todos, then){
	if(todos.length > 0){
		var func = todos.shift();
		func(function(err, result){
			if(err){
				throw err;	
				then(err);
			}else{			
				control.emit("donext", todos, then);					
			}
		});
	}else{			
		then(null);
	}
});


/**
* 描述:下载目录到本地
* 参数:server 远程电脑凭证;
*		remotePath 远程路径;
*		localDir 本地路径,
*		then 回调函数
* 回调:then(err)
*/
function DownloadDir(server, remoteDir,localDir, then){
	GetFileOrDirList(server, remoteDir, false, function(err, dirs){
		if(err){
			throw err;
		}else{
			GetFileOrDirList(server, remoteDir, true, function(err, files){
				if(err){
					throw err;
				}else{					
					dirs.shift();
					dirs.forEach(function(dir){	
						var tmpDir = path.join(localDir, dir.slice(remoteDir.length+1)).replace(/[//]\g/, '\\');
						// 创建目录
						fs.mkdirSync(tmpDir);				
					});
					var todoFiles = [];
					files.forEach(function(file){
						var tmpPath = path.join(localDir, file.slice(remoteDir.length+1)).replace(/[//]\g/, '\\');
						todoFiles.push(function(done){
							DownloadFile(server, file, tmpPath, done);							
							console.log("downloading the "+file);
						});// end of todoFiles.push						
					});
					control.emit("donext", todoFiles, then);
				}
			});
		}
	});
}

/**
* 描述:获取windows上的文件目录以及文件列表信息
* 参数:destDir 本地路径,
*		dirs 目录列表
*		files 文件列表
*/
function GetFileAndDirList(localDir, dirs, files){
	var dir = fs.readdirSync(localDir);
	for(var i = 0; i < dir.length; i ++){
		var p = path.join(localDir, dir[i]);
		var stat = fs.statSync(p); 
		if(stat.isDirectory())
		{
			dirs.push(p);
			GetFileAndDirList(p, dirs, files);
		}
		else
		{
			files.push(p);
		}
	}
}

/**
* 描述:上传文件夹到远程目录
* 参数:server 远程电脑凭证;
*		localDir 本地路径,
*		remotePath 远程路径;
*		then 回调函数
* 回调:then(err)
*/
function UploadDir(server, localDir, remoteDir, then){
	var dirs = [];
	var files = [];
	GetFileAndDirList(localDir, dirs, files);
	
	// 创建远程目录
	var todoDir = [];
	dirs.forEach(function(dir){
		todoDir.push(function(done){			
			var to = path.join(remoteDir, dir.slice(localDir.length+1)).replace(/[\\]/g, '/');
			var cmd = "mkdir -p " + to +"\r\nexit\r\n";
			console.log(cmd);
			Shell(server, cmd, done);
		})// end of push
	});
	
	// 上传文件
	var todoFile = [];
	files.forEach(function(file){
		todoFile.push(function(done){
			var to  = path.join(remoteDir, file.slice(localDir.length+1)).replace(/[\\]/g, '/');
			console.log("upload " + to);
			UploadFile(server, file, to, done);
		});
	});
	
	control.emit("donext", todoDir, function(err){
		if(err){
			throw err;
		}else{			
			control.emit("donext", todoFile, then);
		}
	});
	
}

exports.Shell = Shell;
exports.UploadFile = UploadFile;
exports.DownloadFile = DownloadFile;
exports.GetFileOrDirList = GetFileOrDirList;
exports.DownloadDir = DownloadDir;
exports.UploadDir = UploadDir;

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它可以使JavaScript在服务器端运行。要实现文件上传下载,可以使用Node.js的一些模块和框架来简化开发过程。 对于文件上传,可以使用Multer作为中间件进行数据处理。Multer是一个流行的Node.js中间件,用于处理表单数据,特别是文件上传。以下是一个简单的示例代码: ```javascript const express = require('express'); const multer = require('multer'); const app = express(); const upload = multer({ dest: 'uploads/' }); app.post('/upload', upload.single('file'), (req, res) => { // 处理上传文件 console.log(req.file); res.send('文件上传成功!'); }); app.listen(8080, () => { console.log('服务器已启动,监听端口8080'); }); ``` 上述代码创建了一个基本的Express应用程序,并使用Multer中间件来处理文件上传。`upload.single('file')`表示只接受名为`file`的单个文件。在回调函数中可以进行文件处理的操作。 对于文件下载,可以使用Node.js的内置模块`fs`和`http`来实现。以下是一个简单的示例代码: ```javascript const http = require('http'); const fs = require('fs'); http.createServer((req, res) => { if (req.method === 'GET' && req.url === '/download') { const file = fs.createReadStream('path/to/file.txt'); res.setHeader('Content-disposition', 'attachment; filename=file.txt'); file.pipe(res); } }).listen(8080, () => { console.log('服务器已启动,监听端口8080'); }); ``` 上述代码创建了一个简单的HTTP服务器,当GET请求路径为`/download`时,会将文件作为附件下载。可以通过设置`Content-disposition`头来指定下载文件的名称。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值