node ftp上傳文件夾到服務(wù)器案例詳解
更新時間:2023年04月07日 09:15:29 作者:我說的馬是黑馬
這篇文章主要介紹了node ftp上傳文件夾到服務(wù)器的視線方法,結(jié)合具體實例分析了node.js調(diào)用ftp模塊進行文件上傳的相關(guān)配置、連接、path路徑操作與文件傳輸實現(xiàn)方法,需要的朋友可以參考下
完整代碼示例如下:
const ftp = require('ftp');//連接FTP
const path = require('path');
const client = new ftp();
const fs = require('fs');
//本地文件夾路徑;
const localDirPath = '/test/';
//遠程地址,打開ftp以后的地址,不需要加入host;
const remotePath = '/';
const uploadFiles = [];
const mkDirPromiseArr = [];
const connectionProperties = {
host: '', //ftp地址;
user: '', //用戶名;
password: '', //密碼;
port: 21 //端口;
};
client.connect(connectionProperties);
client.on('ready', () => {
console.log('ftp client is ready');
start();
});
async function start() {
const { err: ea, dir } = await cwd(remotePath);//此處應(yīng)對err做處理
if (ea) {
client.mkdir(remotePath, true, (err) => {
if (err) {
console.log('創(chuàng)建' + remotePath + '文件夾失敗');
upload();
} else {
console.log('創(chuàng)建' + remotePath + '成功');
upload();
}
});
} else {
upload();
}
function upload() {
const filesPath = { files: [] };
getDirAllFilePath(localDirPath, filesPath);
remoteMkDir(filesPath, '');
console.log('準備上傳...');
setTimeout(() => {
Promise.all(mkDirPromiseArr).then(() => {
console.log('開始上傳...');
const tasks = uploadFile();
runPromiseArray(tasks).then(() => {
client.end();
console.warn('上傳完成~');
});
});
}, 3000);
}
}
// 獲取本地的文件地址和路徑;
function getDirAllFilePath(paths, parent) {
const files = fs.readdirSync(paths);
files.forEach(item => {
if (item != '.DS_Store') {
const path = `${paths}/${item}`;
if (isDir(path)) {
getDirAllFilePath(path, parent[item] = { files: [] });
} else if (isFile(path)) {
parent.files.push(item);
}
}
})
}
//創(chuàng)建遠程確實的文件夾;
async function remoteMkDir(obj, _path) {
for (const key in obj) {
if (key === 'files') {
for (let i = 0, len = obj[key].length; i < len; i++) {
const promise = new Promise(async resolve => {
let p = '';
if (_path) {
p = _path + '/';
}
const filePathName = p + obj[key][i];
uploadFiles.push({ path: filePathName, fileName: obj[key][i] });
const ph = remotePath + filePathName.substring(0, filePathName.lastIndexOf('/') + 1);
let { err: ea, dir } = await cwd(ph);//此處應(yīng)對err做處理
if (ea) {
client.mkdir(ph, true, (err) => {
if (err) {
console.log('mkdir' + ph + 'err', err);
resolve(null);
return;
}
console.log('mkdir ' + ph + ' success');
resolve(null);
});
} else {
resolve(null);
}
});
mkDirPromiseArr.push(promise);
}
} else {
let p = '';
if (_path) {
p = _path + '/';
}
remoteMkDir(obj[key], p + key);
}
}
}
//上傳文件;
function uploadFile() {
const tasks = [];
const resourcesPath = localDirPath;
//目標路徑文件夾;
const checkPath = remotePath;
for (let i = 0, len = uploadFiles.length; i < len; i++) {
const task = () => {
return new Promise(async (resolve, reject) => {
const _path = uploadFiles[i].path;
const targetPath = checkPath + _path;
const putPath = resourcesPath + '/' + _path;
const dirpath = path.dirname(targetPath);
const fileName = path.basename(targetPath);
client.cwd(dirpath, (cwdErr, dir) => {
client.pwd((pwdErr, cwd) => {
if (pwdErr) {
resolve(pwdErr)
} else {
client.get(fileName, (err, res) => {
if (res) {
console.log(`${targetPath} =====================已經(jīng)存在了`);
resolve(true);
} else {
const rs = fs.createReadStream(putPath);
client.put(rs, fileName, (putErr, data) => {
if (putErr) {
resolve(err);
} else {
console.log(targetPath + '文件上傳成功');
resolve(true);
}
})
}
});
}
});
})
});
}
tasks.push(task);
}
return tasks;
}
//執(zhí)行Promise的隊列動作;
function runPromiseArray(parray) { //這個方法可以放到G里
let p = Promise.resolve();
for (let promise of parray) {
p = p.then(promise);
}
return p;
}
//切換目錄
async function cwd(dirpath) {
return new Promise((resolve, reject) => {
client.cwd(dirpath, (err, dir) => {
resolve({ err: err, dir: dir });
})
});
}
function isFile(filepath) { //判斷是否是文件 Boolean
let stat = fs.statSync(filepath)
return stat.isFile()
}
function isDir(filepath) { //判斷是否是文件夾 Boolean
let stat = fs.statSync(filepath);
return stat.isDirectory();
}
筆者解讀一下:代碼中的localDirPath為本地需要讀取其中文件,并使用ftp上傳的文件夾。
注意:這里的上傳是針對文件夾中所有的文件夾與文件進行遍歷后的上傳,實際應(yīng)用中,我們可能只需要上傳指定的文件,對此,筆者修改后的腳本如下:
const ftp = require('ftp');//連接FTP
const path = require('path');
const client = new ftp();
const fs = require('fs');
//本地文件夾路徑;
const localDirPath = path.join(__dirname,'/imgtmp/');//待遍歷的本地目錄
//遠程ftp服務(wù)器文件路徑
let remotePath = '/yourweb/images/';
const upFileList = ["202304/202304061415075072.png","202304/202304061415075073.png"];//手動設(shè)置需要上傳的文件
const uploadFiles = [];
const mkDirPromiseArr = [];
client.on('ready',()=>{
console.log('ftp client is ready');
});
const connconfig = {
host: '', //ftp地址;
user: '', //用戶名;
password: '', //密碼;
port: 21 //端口;
}
client.connect(connconfig);
client.on('ready', () => {
console.log('ftp client is ready');
start();
});
async function start() {
const { err: ea, dir } = await cwd(remotePath);//此處應(yīng)對err做處理
if (ea) {
client.mkdir(remotePath, true, (err) => {
if (err) {
console.log('創(chuàng)建' + remotePath + '文件夾失敗');
upload();
} else {
console.log('創(chuàng)建' + remotePath + '成功');
upload();
}
});
} else {
upload();
}
function upload() {
console.log("mkDirPromiseArr==>",mkDirPromiseArr);
// const filesPath = { files: [] };
// getDirAllFilePath(localDirPath, filesPath);
const filesPath = { files: upFileList };//直接給定需要上傳的文件列表
// console.log("遍歷之后的filesPath===>",filesPath);
remoteMkDir(filesPath, '');
console.log('準備上傳...');
setTimeout(() => {
Promise.all(mkDirPromiseArr).then(() => {
console.log('開始上傳...');
const tasks = uploadFile();
runPromiseArray(tasks).then(() => {
client.end();
console.warn('上傳完成~');
});
});
}, 1000);
}
}
// 獲取本地的文件地址和路徑;
function getDirAllFilePath(paths, parent) {
const files = fs.readdirSync(paths);
files.forEach(item => {
if (item != '.DS_Store') {
const path = `${paths}/${item}`;
if (isDir(path)) {
getDirAllFilePath(path, parent[item] = { files: [] });
} else if (isFile(path)) {
parent.files.push(item);
}
}
})
}
//創(chuàng)建遠程缺失的文件夾;
async function remoteMkDir(obj, _path) {
for (const key in obj) {
if (key === 'files') {
for (let i = 0, len = obj[key].length; i < len; i++) {
const promise = new Promise(async resolve => {
let p = '';
if (_path) {
p = _path + '/';
}
const filePathName = p + obj[key][i];
// const filePathName = path.dirname(obj[key][i]);
const fileName = path.basename(obj[key][i]);
// uploadFiles.push({ path: filePathName, fileName: obj[key][i] });
uploadFiles.push({ path: filePathName, fileName: fileName });
const ph = remotePath + filePathName.substring(0, filePathName.lastIndexOf('/') + 1);
let { err: ea, dir } = await cwd(ph);//此處應(yīng)對err做處理
if (ea) {
client.mkdir(ph, true, (err) => {
if (err) {
console.log('mkdir' + ph + 'err', err);
resolve(null);
return;
}
console.log('mkdir ' + ph + ' success');
resolve(null);
});
} else {
resolve(null);
}
});
mkDirPromiseArr.push(promise);
}
} else {
let p = '';
if (_path) {
p = _path + '/';
}
remoteMkDir(obj[key], p + key);
}
}
}
//上傳文件;
function uploadFile() {
const tasks = [];
const resourcesPath = localDirPath;
//目標路徑文件夾;
const checkPath = remotePath;
for (let i = 0, len = uploadFiles.length; i < len; i++) {
const task = () => {
return new Promise(async (resolve, reject) => {
const _path = uploadFiles[i].path;
// const _path = uploadFiles[i];
const targetPath = checkPath + _path;
const putPath = resourcesPath + '/' + _path;
const dirpath = path.dirname(targetPath);
const fileName = path.basename(targetPath);
client.cwd(dirpath, (cwdErr, dir) => {
client.pwd((pwdErr, cwd) => {
if (pwdErr) {
resolve(pwdErr)
} else {
client.get(fileName, (err, res) => {
if (res) {
console.log(`${targetPath} =====================已經(jīng)存在了`);
resolve(true);
} else {
const rs = fs.createReadStream(putPath);
client.put(rs, fileName, (putErr, data) => {
if (putErr) {
resolve(err);
} else {
console.log(targetPath + '文件上傳成功');
resolve(true);
}
})
}
});
}
});
})
});
}
tasks.push(task);
}
return tasks;
}
//執(zhí)行Promise的隊列動作;
function runPromiseArray(parray) { //這個方法可以放到G里
let p = Promise.resolve();
for (let promise of parray) {
p = p.then(promise);
}
return p;
}
//切換目錄
async function cwd(dirpath) {
return new Promise((resolve, reject) => {
client.cwd(dirpath, (err, dir) => {
resolve({ err: err, dir: dir });
})
});
}
function isFile(filepath) { //判斷是否是文件 Boolean
let stat = fs.statSync(filepath)
return stat.isFile()
}
function isDir(filepath) { //判斷是否是文件夾 Boolean
let stat = fs.statSync(filepath);
return stat.isDirectory();
}PS:筆者此處使用了一個upFileList數(shù)組保存了需要上傳到服務(wù)器的圖片文件路徑(包括文件夾與文件名),感興趣的朋友可以測試一下看看效果~
相關(guān)文章
package-lock.json解決依賴的版本管理使用詳解
這篇文章主要為大家介紹了package-lock.json解決依賴的版本管理使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08
Node.js?網(wǎng)絡(luò)框架koa?compose中間件使用解析
這篇文章主要為大家介紹了Node.js?網(wǎng)絡(luò)框架koa?compose中間件使用解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12

