通过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});
})
});
}