使用nodejs连接ftp上传下载

使用nodejs连接ftp上传下载

月光魔力鸭

2019-01-16 10:20 阅读 5372 喜欢 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


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
介绍几个日常开发中常用的几个小工具: anywhere / anywhere-auth / watchlessc / changeext
跑了一个千库网的自动签到,在windows上测试的时候好好的,图片也没问题,可是放到linux服务器就不行了,总是登录不上不说,图片都不一样
前段时间帮朋友下歌放在车上听..结果好多都是ncm格式,伤心 ,搜索了下发现基本上这格式解密有好多昂,可惜UI我都不太想要..决定抄一下,自己做一个。 这里先记录下核心代码,回头补充个UI 做个小程序。
产品版本更新的时候经常会有一些数据库的差异,如果版本管理好的话,一步一步升级即可.. 但是如果好久没更新的话,还是有很多不确定的,只能挨着比对表和字段。比对了一次就烦了,写了这么一个工具,查询差异表和字段并给出sql语句。
当我们想实现一个自己的库或模块后,发布的话,需要发布到npm上才能下载。以下是具体步骤
最近有接触到针对二维码进行识别的功能,然后对图片进行位置纠正、二维码扫描,并将数据进行整理。以下是通过nodejs做的,相对简单一些,没有太过严格,识别率也不是很高大约80%左右
今天写文章,突然发现自己常用的素材站换成了webp格式的图片.. 可惜本站还没准备加这个支持,所以准备加个webp转jpg的小功能,继续使用啦。