使用nodejs连接ftp上传下载

使用nodejs连接ftp上传下载

月光魔力鸭

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


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
前几天给朋友帮忙,想要一个一模一样的网站...自告奋勇去帮忙.. 结果发现之前一直没处理过类似的情况,虽然也写过爬虫,不过看了下网站,也不算麻烦。于是简单实现了这个自动抓站的功能,最终整理成为一个自动抓站的工具,能省很多的事情。
记录下在linux环境下安装phantomjs 的步骤,防止遗忘...
有一个需求,需要公司的LOGO信息,但是没有,只有公司的名字,想着先生成个默认的(本来是可以通过前端判断然后合成的..但是不想改小程序了),于是开始准备处理。
通过node-xlsx模块读取excel和写入
我们项目一直在使用puppeteer 生成pdf ,整体的思路是没有问题的,而且在开发环境运行了好久了,但是部署后总会有各种各样的报错。各种so文件找不到等等 。
关于js的编译和压缩,之前做过一个小工具了,主要就是自己项目成员大都没有这部分的技能,导致发布的时候总需要去编译压缩下.. 最终做了个命令行小工具.. 问题不在这里,前一阵子做压缩的时候发现压缩后竟然是undefined.最终才发现是es6的语法问题。
互联网应用经常需要存储用户上传的图片,比如facebook相册。 facebook目前存储了2600亿张照片,总大小为20PB,每张照片约为80KB。用户每周新增照片数量为10亿。(总大小60TB),平均每秒新增3500张照片(3500次写请求),读操作峰值可以达到每秒百万次
在我们做运维或者小工具的时候,总会有些需要提醒的事情,比如服务器宕机或者天气提醒,但是发email又会不够及时或者可能会忽略,那么短信就是一个不错的选择了