使用nodejs連線ftp上傳下載

透過nodejs連線ftp,對ftp進行操作,包括查詢列表、下載、上傳。

依賴

//ftp 模組是目前找到的還不錯的,對於ftp的基本功能都支援npm install ftp

連線ftp

const ftp = require(‘ftp’);//連線FTPconst client = new ftp();client。on(‘ready’,()=>{ console。log(‘ftp client is ready’);});client。connect({ host : ‘***。***。***。***’, port : ‘****’, user : ‘***’, password : ‘***’, keepalive : 1000});

使用nodejs連線ftp上傳下載

呼叫後

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();

使用nodejs連線ftp上傳下載

獲取結果

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’);//連線FTPconst 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}); }) });}

issue 傳送門

參考資料

https://github。com/mscdex/node-ftp

https://github。com/mscdex/node-ftp/issues/73