@winner-fed/ftp-deploy
v4.0.11
Published
FTP uploads local files to the target server
Readme
@winner-fed/ftp-deploy
一个简单易用的 FTP/SFTP 文件部署工具
简介
@winner-fed/ftp-deploy 是一个专门用于将本地文件上传到远程服务器的工具库。它支持 FTP 和 SFTP 两种协议,提供了灵活的文件过滤和上传配置选项,适用于前端项目的自动化部署场景。
特性
- 🚀 支持 FTP 和 SFTP 两种协议
- 📁 灵活的文件包含/排除规则配置
- 🔄 支持增量上传和全量替换
- 📊 详细的上传进度和日志信息
- 🛡️ 安全的连接配置和错误处理
- 🎯 支持 TypeScript,提供完整的类型定义
- ⚡ 基于 Promise 的异步操作
安装
npm install @winner-fed/ftp-deploy
# 或
yarn add @winner-fed/ftp-deploy
# 或
pnpm add @winner-fed/ftp-deploy快速开始
基础用法
const { FtpDeployer } = require('@winner-fed/ftp-deploy');
const path = require('path');
const ftpDeploy = new FtpDeployer();
// 基本配置
const config = {
user: 'your-username',
password: 'your-password',
host: 'your-server.com',
port: 21, // FTP 默认端口
localPath: path.join(__dirname, 'dist'),
remotePath: '/var/www/html',
include: ['*'],
exclude: [],
deleteRemote: false,
forcePasv: true,
sftp: false
};
// 执行部署
ftpDeploy
.deploy(config)
.then((result) => {
console.log('部署成功:', result);
})
.catch((error) => {
console.error('部署失败:', error);
});SFTP 部署示例
const { FtpDeployer } = require('@winner-fed/ftp-deploy');
const path = require('path');
const ftpDeploy = new FtpDeployer();
const config = {
user: 'root',
password: 'your-password',
host: '192.168.1.100',
port: 22, // SFTP 默认端口
localPath: path.join(__dirname, 'build'),
remotePath: '/usr/local/nginx/html/my-app',
include: ['*', '**/*'], // 包含所有文件和子目录
exclude: [
'**/*.map', // 排除 source map 文件
'node_modules/**', // 排除 node_modules
'.git/**', // 排除 git 文件
'*.log' // 排除日志文件
],
deleteRemote: true, // 上传前清空远程目录
forcePasv: true,
sftp: true // 使用 SFTP 协议
};
ftpDeploy
.deploy(config)
.then((result) => {
console.log('SFTP 部署成功:', result);
})
.catch((error) => {
console.error('SFTP 部署失败:', error);
});API 文档
FtpDeployer 类
构造函数
const ftpDeploy = new FtpDeployer();deploy(config: UserConfig): Promise
执行文件部署操作。
参数:
config: 部署配置对象,详见下方配置说明
返回值:
Promise<any>: 部署结果的 Promise 对象
配置说明
UserConfig 接口
interface UserConfig {
/**
* 目标服务器登录用户名
* @example 'root', 'admin', 'deploy-user'
*/
user: string;
/**
* 目标服务器登录密码
* @example 'your-password'
*/
password: string;
/**
* 目标服务器主机地址
* 可以是 IP 地址或域名
* @example '192.168.1.100', 'example.com'
*/
host: string;
/**
* 目标服务器端口
* FTP 默认端口: 21
* SFTP 默认端口: 22
* @default 21 (FTP) | 22 (SFTP)
*/
port: number;
/**
* 本地文件路径
* 支持相对路径和绝对路径
* @example './dist', '/home/user/project/build'
*/
localPath: string;
/**
* 目标服务器上传路径
* 远程服务器的目标目录
* @example '/var/www/html', '/usr/local/nginx/html/my-app'
*/
remotePath: string;
/**
* 包含的文件模式
* 使用 glob 模式匹配文件
* @example ["*.html", "*.css", "*.js", "assets/**"]
*/
include: Array<string>;
/**
* 排除的文件模式
* 使用 glob 模式排除不需要上传的文件
* @example ["**/*.map", "node_modules/**", ".git/**"]
*/
exclude: Array<string>;
/**
* 上传前是否删除远程目录的所有文件
* true: 全量替换(先删除后上传)
* false: 增量上传(只上传变更文件)
* @default false
*/
deleteRemote: boolean;
/**
* 是否强制使用被动模式
* 建议保持为 true,避免防火墙问题
* @default true
*/
forcePasv: boolean;
/**
* 是否使用 SFTP 协议
* true: 使用 SFTP (SSH File Transfer Protocol)
* false: 使用 FTP (File Transfer Protocol)
* @default false
*/
sftp: boolean;
}文件匹配模式说明
include 配置示例
// 包含所有文件
include: ['*', '**/*'];
// 只包含特定类型文件
include: ['*.html', '*.css', '*.js'];
// 包含特定目录
include: ['dist/**', 'assets/**'];
// 混合匹配
include: ['index.html', 'static/**', '*.json'];exclude 配置示例
// 常见的排除配置
exclude: [
'**/*.map', // 所有 source map 文件
'node_modules/**', // node_modules 目录
'.git/**', // git 相关文件
'*.log', // 日志文件
'.DS_Store', // macOS 系统文件
'Thumbs.db', // Windows 系统文件
'**/.env*', // 环境变量文件
'coverage/**', // 测试覆盖率文件
'**/*.test.js', // 测试文件
'**/*.spec.js' // 测试文件
];使用场景
1. 前端项目部署
// 部署 React/Vue 等前端项目
const config = {
user: 'deploy',
password: 'deploy123',
host: 'your-server.com',
port: 22,
localPath: './build', // 或 './dist'
remotePath: '/var/www/html/my-app',
include: ['*', '**/*'],
exclude: ['**/*.map', '.env*'],
deleteRemote: true, // 全量替换
sftp: true
};2. 静态资源上传
// 只上传静态资源文件
const config = {
user: 'assets-user',
password: 'password',
host: 'cdn.example.com',
port: 21,
localPath: './assets',
remotePath: '/cdn/assets',
include: ['*.png', '*.jpg', '*.gif', '*.svg', '*.css', '*.js'],
exclude: [],
deleteRemote: false, // 增量上传
sftp: false
};3. 多环境部署
const environments = {
development: {
host: 'dev.example.com',
remotePath: '/var/www/dev'
},
staging: {
host: 'staging.example.com',
remotePath: '/var/www/staging'
},
production: {
host: 'prod.example.com',
remotePath: '/var/www/prod'
}
};
const env = process.env.NODE_ENV || 'development';
const envConfig = environments[env];
const config = {
user: 'deploy',
password: process.env.DEPLOY_PASSWORD,
host: envConfig.host,
port: 22,
localPath: './dist',
remotePath: envConfig.remotePath,
include: ['*', '**/*'],
exclude: ['**/*.map'],
deleteRemote: true,
sftp: true
};错误处理
常见错误及解决方案
ftpDeploy
.deploy(config)
.then((result) => {
console.log('部署成功:', result);
})
.catch((error) => {
console.error('部署失败:', error);
// 根据错误类型进行处理
if (error.code === 'ECONNREFUSED') {
console.error('连接被拒绝,请检查主机地址和端口');
} else if (error.code === 'ENOTFOUND') {
console.error('主机不存在,请检查主机地址');
} else if (error.code === 530) {
console.error('登录失败,请检查用户名和密码');
} else if (error.code === 550) {
console.error('权限不足或路径不存在');
} else {
console.error('未知错误:', error.message);
}
});连接超时处理
// 添加超时处理
const deployWithTimeout = (config, timeout = 30000) => {
return Promise.race([
ftpDeploy.deploy(config),
new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('部署超时'));
}, timeout);
})
]);
};
deployWithTimeout(config, 60000) // 60秒超时
.then((result) => console.log('部署成功:', result))
.catch((error) => console.error('部署失败:', error));最佳实践
1. 安全配置
// 使用环境变量存储敏感信息
const config = {
user: process.env.FTP_USER,
password: process.env.FTP_PASSWORD,
host: process.env.FTP_HOST,
port: parseInt(process.env.FTP_PORT) || 22
// ... 其他配置
};2. 配置文件管理
// deploy.config.js
module.exports = {
development: {
user: 'dev-user',
host: 'dev.example.com',
remotePath: '/var/www/dev'
},
production: {
user: 'prod-user',
host: 'prod.example.com',
remotePath: '/var/www/prod'
}
};
// deploy.js
const config = require('./deploy.config.js');
const env = process.env.NODE_ENV || 'development';
const deployConfig = {
...config[env],
password: process.env.DEPLOY_PASSWORD
// ... 其他通用配置
};3. 部署脚本集成
// package.json
{
"scripts": {
"build": "npm run build:prod",
"deploy:dev": "NODE_ENV=development node deploy.js",
"deploy:prod": "NODE_ENV=production node deploy.js",
"deploy": "npm run build && npm run deploy:prod"
}
}注意事项
安全性:
- 不要在代码中硬编码密码
- 使用环境变量或配置文件管理敏感信息
- 建议使用 SFTP 而不是 FTP,提供更好的安全性
网络连接:
- 确保服务器防火墙允许相应端口的连接
- FTP 被动模式通常更容易通过防火墙
文件权限:
- 确保远程用户有目标目录的写入权限
- 上传后可能需要设置正确的文件权限
大文件上传:
- 大文件上传可能需要更长时间
- 建议设置合适的超时时间
路径格式:
- Windows 系统注意路径分隔符
- 建议使用
path.join()处理路径
更新日志
详细的更新日志请查看 CHANGELOG.md。
许可证
MIT License
贡献
欢迎提交 Issue 和 Pull Request 来改进这个项目。
