node ftp上传文件夹到服务器案例详解

 更新时间:2023年04月07日 09:15:29   作者:我说的马是黑马  
这篇文章主要介绍了node ftp上传文件夹到服务器的视线方法,结合具体实例分析了node.js调用ftp模块进行文件上传的相关配置、连接、path路径操作与文件传输实现方法,需要的朋友可以参考下

完整代码示例如下:

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);//此处应对err做处理
    if (ea) {
        client.mkdir(remotePath, true, (err) => {
            if (err) {
                console.log('创建' + remotePath + '文件夹失败');
                upload();
            } else {
                console.log('创建' + 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);
            }
        }
    })
}
//创建远程确实的文件夹;
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);//此处应对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} =====================已经存在了`);
                                    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;
}
//执行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上传的文件夹。

注意:这里的上传是针对文件夹中所有的文件夹与文件进行遍历后的上传,实际应用中,我们可能只需要上传指定的文件,对此,笔者修改后的脚本如下:

const ftp = require('ftp');//连接FTP
const path = require('path');
const client = new ftp();
const fs = require('fs');

//本地文件夹路径;
const localDirPath = path.join(__dirname,'/imgtmp/');//待遍历的本地目录
//远程ftp服务器文件路径
let remotePath = '/yourweb/images/';
const upFileList = ["202304/202304061415075072.png","202304/202304061415075073.png"];//手动设置需要上传的文件
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);//此处应对err做处理
    if (ea) {
        client.mkdir(remotePath, true, (err) => {
            if (err) {
                console.log('创建' + remotePath + '文件夹失败');
                upload();
            } else {
                console.log('创建' + 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);
            }
        }
    })
}
 
 
//创建远程缺失的文件夹;
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);//此处应对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} =====================已经存在了`);
                                    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;
}
 
//执行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数组保存了需要上传到服务器的图片文件路径(包括文件夹与文件名),感兴趣的朋友可以测试一下看看效果~

相关文章

  • package-lock.json解决依赖的版本管理使用详解

    package-lock.json解决依赖的版本管理使用详解

    这篇文章主要为大家介绍了package-lock.json解决依赖的版本管理使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 解决修复npm安装全局模块权限的问题

    解决修复npm安装全局模块权限的问题

    今天小编就为大家分享一篇解决修复npm安装全局模块权限的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • 使用Node.js实现遍历文件夹下所有文件

    使用Node.js实现遍历文件夹下所有文件

    在使用Node.js处理文件或文件夹时,我们有时需要遍历文件夹中的所有文件和子文件夹以查找特定的文件或执行某些操作,这里将提供一些基本的例子来演示如何使用Node.js遍历文件夹,需要的朋友可以参考下
    2023-08-08
  • Node.js 网络框架koa compose中间件使用解析

    Node.js 网络框架koa compose中间件使用解析

    这篇文章主要为大家介绍了Node.js 网络框架koa compose中间件使用解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • nodejs读取本地mp3和mp4等媒体文件并播放的案例

    nodejs读取本地mp3和mp4等媒体文件并播放的案例

    fs模块是nodejs官方提供用来操作文件的模块,下面这篇文章主要给大家介绍了关于nodejs读取本地mp3和mp4等媒体文件并播放的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • 你或许不知道的一些npm实用技巧

    你或许不知道的一些npm实用技巧

    这篇文章主要给大家介绍了一些你或许不知道的npm实用技巧,分享一些 npm 包管理工具的实用小窍门,希望能够略微提高下前端、Node.js 开发者的生活质量,需要的朋友可以参考下
    2019-07-07
  • package.json的版本号更新优化方法

    package.json的版本号更新优化方法

    这篇文章主要为大家介绍了package.json的版本号更新优化方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 详解Node.js如何开发命令行工具

    详解Node.js如何开发命令行工具

    追求更高的效率是码农不断的追求。选择合适的工具,合理搭配使用,既能提高一部分开发效率,又能改善写代码时的心情。使用Node.js开发命令行工具是开发者应该掌握的一项技能,适当编写命令行工具以提高开发效率。
    2016-08-08
  • Node.js插件安装图文教程

    Node.js插件安装图文教程

    Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。本文给大家介绍Node.js插件安装的教程,非常实用,特此分享给大家,需要的朋友一起学习吧
    2016-05-05
  • Node.js中如何合并两个复杂对象详解

    Node.js中如何合并两个复杂对象详解

    下面这篇文章主要给大家介绍了在Node.js中如何合并两个复杂对象的方法,文中给出了详细的示例代码,相信对大家的理解和学习具有一定的参考借鉴价值,有需要的朋友可以参考,下面来一起看看吧。
    2016-12-12

最新评论