使用nodejs连接ftp上传下载

使用nodejs连接ftp上传下载

月光魔力鸭

2019-01-16 10:20 阅读 5331 喜欢 9 ftp上传 nodejs连接ftp

通过nodejs连接ftp,对ftp进行操作,包括查询列表、下载、上传。

依赖

//ftp 模块是目前找到的还不错的,对于ftp的基本功能都支持
npm install ftp

连接ftp

const ftp = require('ftp');//连接FTP
const client = new ftp();
client.on('ready',()=>{
	console.log('ftp client is ready');
});
client.connect({
    host : '***.***.***.***',
	port : '****',
	user : '***',
	password : '***',
	keepalive : 1000
});

调用后

ftp 获取列表 list

//列出目标目录
function list(dirpath){
	return new Promise((resolve,reject)=>{
		client.list((err,files)=>{
			resolve({err : err,files : files});
		})
	});
}
async function test (){
	//list 列表功能
	let {err,files} = await list();
	if(err){
		console.log(err);
		return
	}
	console.log(`获得文件列表:`+files.length);
	console.log(files);
}
test();

获取结果

ftp 目录切换

//切换目录
function cwd(dirpath){
	return new Promise((resolve,reject)=>{
		client.cwd(dirpath,(err,dir)=>{
			resolve({err : err,dir : dir});
		})
	});
}

FBI WARNING : 这里提醒下,在本示例中的所有代码都在同一个文件中,后面会给出完整示例代码。

有了目录切换,那么在list函数中的dirpath就可以使用啦。如下:

//列出目标目录
//列出目标目录
async function list(dirpath){
	let {err : ea,dir } = await cwd(dirpath);
	return new Promise((resolve,reject)=>{
		client.list((err,files)=>{
			resolve({err : err,files : files})
		})
	});
}

ftp 下载文件

//下载文件
async function get(filePath){
	const dirpath = path.dirname(filePath);
	const fileName = path.basename(filePath);
	let {err : ea,dir} = await cwd(dirpath);
	return new Promise((resolve,reject)=>{
		client.get(fileName,(err,rs)=>{
			let ws = fs.createWriteStream(fileName);
			rs.pipe(ws);
			resolve({err : err});	
		});
	});
}

ftp 上传文件

//将文件上传到ftp目标地址
async function put(currentFile,targetFilePath){
	const dirpath = path.dirname(targetFilePath);
	const fileName = path.basename(targetFilePath);
	const rs = fs.createReadStream(currentFile);
	let {err : ea,dir} = await cwd(dirpath);//此处应对err做处理
	if(ea){
		return Promise.resolve({err : ea});
	}
	return new Promise((resolve,reject)=>{
		client.put(rs,fileName,(err)=>{
			resolve({err : err});
		})
	});
}

ftp 断点下载

fs.stat(localFile,(err,stats)=>{
        var startSize = 0;
        if(err){
            console.log('no file here');
        }else{
            startSize = stats.size;
        }
        console.log(`已经下载:${startSize},从此处开始下载`);
        c.restart(startSize,err=>{
            if(err){
                console.log(err);
                process.exit(0);
            }
            c.get(targetFile,(err,rs)=>{
                console.log('start download');
                console.log(rs);
                rs.on('data',data=>{
                    console.log(`写入${data.length}`);
                    rs.pause();
                    fs.appendFile(localFile,data,()=>{
                        rs.resume();
                    });
                })
                rs.on('close',()=>{
                    console.log('download complete')
                    c.end();
                })
                // rs.pipe(fs.createWriteStream(localFile,{start : startSize}))
            })
        })
    })

断点下载目前有个问题还没解决,如果ftp服务器是filezilla server的话,是不行,会追加文件,也可能是我设置的问题,不过目前还没解决方案,如果各位有的话,麻烦给留个言,谢谢啦。

具体的示例截图这里就不展示了,大家可以拿了demo自己测试下。

完整示例代码

const ftp = require('ftp');//连接FTP
const path = require('path');
const client = new ftp();
const fs = require('fs');

client.on('ready',()=>{
	console.log('ftp client is ready');
});
client.on('close',()=>{
	console.log('ftp client has close')
});
client.on('end',()=>{
	console.log('ftp client has end')
});
client.on('error',(err)=>{
	console.log('ftp client has an error : '+ JSON.stringify(err))
});
client.connect({
    host : '***',//这个就不提供啦
	port : '***',
	user : '***',
	password : '***',
	keepalive : 1000
});
//列出目标目录
async function list(dirpath){
	let {err : ea,dir } = await cwd(dirpath);
	return new Promise((resolve,reject)=>{
		client.list((err,files)=>{
			resolve({err : err,files : files})
		})
	});
}
//切换目录
function cwd(dirpath){
	return new Promise((resolve,reject)=>{
		client.cwd(dirpath,(err,dir)=>{
			resolve({err : err,dir : dir});
		})
	});
}
//下载文件
async function get(filePath){
	const dirpath = path.dirname(filePath);
	const fileName = path.basename(filePath);
	let {err : ea,dir} = await cwd(dirpath);
	return new Promise((resolve,reject)=>{
		client.get(fileName,(err,rs)=>{
			let ws = fs.createWriteStream(fileName);
			rs.pipe(ws);
			resolve({err : err});	
		});
	});
}
//将文件上传到ftp目标地址
async function put(currentFile,targetFilePath){
	const dirpath = path.dirname(targetFilePath);
	const fileName = path.basename(targetFilePath);
	const rs = fs.createReadStream(currentFile);
	let {err : ea,dir} = await cwd(dirpath);//此处应对err做处理
	if(ea){
		return Promise.resolve({err : ea});
	}
	return new Promise((resolve,reject)=>{
		client.put(rs,fileName,(err)=>{
			resolve({err : err});
		})
	});
}
async function test (){
	//list 列表功能
	let {err,files} = await list('/attachment/byycampus/resource');
	if(err){
		console.log(err);
		return
	}
	console.log(`获得文件列表:`+files.length);
	console.log(files);
	
	//下载文件
	let {err : ea} = await get('/attachment/byycampus/resource/201812/14/201812141035222541381967.jpg');
	if(ea){
		console.log(ea);
		return;
	}
	console.log('文件下载成功')

	//文件上传
	let {err : eb} = await put('201812141035222541381967.jpg','/attachment/a.jpg');
	if(eb){
		console.log(eb);
		return;
	}
	console.log('文件上传成功')
}
test();

额外赠送

关于在上传过程中或下载过程中获得速率的问题,在github上也有提出来的,这里简单说下大体的思路,具体可以查看issue.

//将文件上传到ftp目标地址
async function put(currentFile,targetFilePath){
	const dirpath = path.dirname(targetFilePath);
	const fileName = path.basename(targetFilePath);
	const rs = fs.createReadStream(currentFile);
//速率
rs.on('data',d=>{
//在这里把上传的文件的大小记录下来,然后速率可以每隔一秒检查一次已经上传的大小,然后根据上一次的文件大小来计算。
})
	let {err : ea,dir} = await cwd(dirpath);//此处应对err做处理
	if(ea){
		return Promise.resolve({err : ea});
	}
	return new Promise((resolve,reject)=>{
		client.put(rs,fileName,(err)=>{
			resolve({err : err});
		})
	});
}

undefined

参考资料

转载请注明出处: https://chrunlee.cn/article/nodejs-ftp-put-get.html


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
最近在折腾的时候又想写less了,但是换框架了,成了thinkjs,考虑到开发阶段一直编译编译less的情况..最终根据middleware的特点实现了一个超级简单的less中间件。
在我们做运维或者小工具的时候,总会有些需要提醒的事情,比如服务器宕机或者天气提醒,但是发email又会不够及时或者可能会忽略,那么短信就是一个不错的选择了
在开发的时候,经常会有css js 文件的变更,然后部署后发现没有起到作用,最终发现是缓存的问题,如何来方便的解决
近期有个小工具,需要使用到本地数据库,想使用sqlite ,本来以为是个手到擒来的活... 没成想卡在了开始上。
前段时间做了个微信小程序反编译的小东西,不过因为功能不全,没加分包处理,正好处理下加上,又考虑到后续可能的更新情况,准备上手增加下更新功能。
前段时间学习到了nodejs的net模块这部分,正好想实现一个局域网内的文件下载小demo,噔噔噔噔... 兴趣推动 ,马上搞一搞。
记录下在linux环境下安装phantomjs 的步骤,防止遗忘...
分享一个自动抓取静态站资源的小工具,可以在抓取某个静态站点的时候方便很多,尤其是如果页面比较多的话,会很难受,而且会自动将资源进行归类,如果一个页面一个页面的保存的话,那就比较费劲了。