通过nodejs连接ftp,对ftp进行操作,包括查询列表、下载、上传。
依赖
//ftp 模块是目前找到的还不错的,对于ftp的基本功能都支持 npm install ftp
连接ftp
const ftp = require('ftp');//连接FTP const client = new ftp(); client.on('ready',()=>{ con('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){ con(err); return } con(`获得文件列表:`+); con(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 = (filePath); const fileName = (filePath); let {err : ea,dir} = await cwd(dirpath); return new Promise((resolve,reject)=>{ client.get(fileName,(err,rs)=>{ let ws = (fileName); rs.pipe(ws); resolve({err : err}); }); }); }
ftp 上传文件
//将文件上传到ftp目标地址 async function put(currentFile,targetFilePath){ const dirpath = (targetFilePath); const fileName = (targetFilePath); const rs = (currentFile); let {err : ea,dir} = await cwd(dirpath);//此处应对err做处理 if(ea){ return Promi({err : ea}); } return new Promise((resolve,reject)=>{ client.put(rs,fileName,(err)=>{ resolve({err : err}); }) }); }
ftp 断点下载
(localFile,(err,stats)=>{ var startSize = 0; if(err){ con('no file here'); }else{ startSize = ; } con(`已经下载:${startSize},从此处开始下载`); c.restart(startSize,err=>{ if(err){ con(err); (0); } c.get(targetFile,(err,rs)=>{ con('start download'); con(rs); rs.on('data',data=>{ con(`写入${da}`); rs.pause(); (localFile,data,()=>{ rs.resume(); }); }) rs.on('close',()=>{ con('download complete') c.end(); }) // rs.pipe((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',()=>{ con('ftp client is ready'); }); client.on('close',()=>{ con('ftp client has close') }); client.on('end',()=>{ con('ftp client has end') }); client.on('error',(err)=>{ con('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 = (filePath); const fileName = (filePath); let {err : ea,dir} = await cwd(dirpath); return new Promise((resolve,reject)=>{ client.get(fileName,(err,rs)=>{ let ws = (fileName); rs.pipe(ws); resolve({err : err}); }); }); } //将文件上传到ftp目标地址 async function put(currentFile,targetFilePath){ const dirpath = (targetFilePath); const fileName = (targetFilePath); const rs = (currentFile); let {err : ea,dir} = await cwd(dirpath);//此处应对err做处理 if(ea){ return Promi({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){ con(err); return } con(`获得文件列表:`+); con(files); //下载文件 let {err : ea} = await get('/attachment/byycampus/resource/201812/14;); if(ea){ con(ea); return; } con('文件下载成功') //文件上传 let {err : eb} = await put('2022541381967.jpg','/attachmen;); if(eb){ con(eb); return; } con('文件上传成功') } test();
额外赠送
关于在上传过程中或下载过程中获得速率的问题,在github上也有提出来的,这里简单说下大体的思路,具体可以查看issue.
//将文件上传到ftp目标地址 async function put(currentFile,targetFilePath){ const dirpath = (targetFilePath); const fileName = (targetFilePath); const rs = (currentFile); //速率 rs.on('data',d=>{ //在这里把上传的文件的大小记录下来,然后速率可以每隔一秒检查一次已经上传的大小,然后根据上一次的文件大小来计算。 }) let {err : ea,dir} = await cwd(dirpath);//此处应对err做处理 if(ea){ return Promi({err : ea}); } return new Promise((resolve,reject)=>{ client.put(rs,fileName,(err)=>{ resolve({err : err}); }) }); }
issue 传送门
参考资料
- /issues/73