Repository navigation
Expand file tree
/
Copy pathssh2Utils.js
More file actions
159 lines (145 loc) · 6.47 KB
/
Copy pathssh2Utils.js
File metadata and controls
159 lines (145 loc) · 6.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { Client } from 'ssh2';
import path from 'path';
// 创建一个包含所有SSH相关工具方法的对象
const ssh2Utils = {
// 连接到SSH服务器并返回连接对象(支持async/await)
connectSSH: async function (serverConfig) {
const conn = new Client();
return new Promise((resolve, reject) => {
conn.on('ready', () => {
console.log('- ssh 链接成功...');
resolve(conn);
});
conn.on('error', (err) => {
reject(err);
});
conn.connect(serverConfig);
});
},
// 获取SFTP对象(支持async/await)
getSFTP: async function (conn) {
return new Promise((resolve, reject) => {
conn.sftp((err, sftp) => {
if (err) {
reject(err);
} else {
resolve(sftp);
}
});
});
},
// 在服务器上检查远程目录是否存在(支持async/await)
checkRemoteDirExists: async function (sftp, remoteDirPath) {
return new Promise((resolve, reject) => {
sftp.stat(remoteDirPath, (err, stats) => {
if (err) {
if (err.code === 'ENOENT' || err.code == 2) {
resolve(false);
} else {
reject(err);
}
} else {
resolve(true);
}
});
});
},
// 在服务器上创建远程目录(如果不存在),支持async/await)
createRemoteDirIfNotExists: async function (conn, localFilePath, remoteDirPaths) {
const sftp = await this.getSFTP(conn);
for (let i = 0; i < remoteDirPaths.length; i++) {
let remoteDirPath = remoteDirPaths[i];
remoteDirPath = this.processPath(`${remoteDirPath}${localFilePath}`);
// console.log(remoteDirPath, remoteDirPath, path.dirname(remoteDirPath))
const dirs = remoteDirPath.split('/').filter(d => d);
let currentDir = '';
// console.log(dirs)
const createDirPromises = [];
const THAT = this;
for (let i = 0; i < dirs.length; i++) {
currentDir += `/${dirs[i]}`;
// console.log('创建目录', currentDir);
(function (currentDir) {
const statPromise = new Promise((resolveStat, rejectStat) => {
THAT.checkRemoteDirExists(sftp, currentDir).then((exists) => {
if (!exists) {
// console.log('创建:', currentDir);
sftp.mkdir(currentDir, (err) => {
if (err) {
if (err.code === 'EACCES') {
rejectStat(new Error(`- 在服务器 ${conn.config.host} 上创建文件夹 ${currentDir} 时权限不足,请检查相关权限设置。`));
} else if (err.code === 'ENOENT' || err.code == 2) {
rejectStat(new Error(`- 创建文件夹 ${currentDir} 时,上级目录不存在,请检查目标路径是否正确。`));
} else {
rejectStat(err);
}
} else {
console.log(`- 在服务器 ${conn.config.host} 上创建文件夹 ${currentDir}`);
resolveStat();
}
});
} else {
resolveStat();
}
}).catch(rejectStat);
});
createDirPromises.push(statPromise);
})(currentDir)
}
try {
await Promise.all(createDirPromises);
} catch (error) {
reject(error);
}
}
},
// 通过SFTP上传文件到服务器,支持async/await)
uploadFileToServer: async function (conn, localFilePath, remoteDirPaths) {
const sftp = await this.getSFTP(conn);
// 创建一个数组来存储所有上传任务的Promise
const uploadPromises = [];
for (let i = 0; i < remoteDirPaths.length; i++) {
const remoteDirPath = remoteDirPaths[i];
const remoteFilePath = `${remoteDirPath}${localFilePath}`;
const localFileP = `${process.env.LOCAL_PATH}/${localFilePath}`;
const uploadPromise = new Promise((resolve, reject) => {
sftp.fastPut(localFileP, remoteFilePath, (err) => {
if (err) {
console.log(err)
if (err.code === 'ENOENT' || err.code == 2) {
reject(new Error(`- 文件 ${localFileP} 在本地不存在,请检查路径是否正确。`));
} else if (err.code === 'EPERM') {
reject(new Error(`- 上传文件 ${localFileP} 到服务器 ${conn.config.host} 时权限不足,请检查相关权限设置。`));
} else {
reject(err);
}
} else {
console.log(`- 文件 ${localFileP} 已成功上传到服务器 ${conn.config.host}${remoteFilePath}`);
resolve();
}
});
});
uploadPromises.push(uploadPromise);
}
// 使用Promise.all来并行等待所有上传任务完成
return await Promise.all(uploadPromises);
},
// 关闭SSH连接,支持async/await)
closeSSHConnection: async function (conn) {
await new Promise((resolve, reject) => {
conn.end((err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
},
// 处理传入路径,若最后是文件则去掉文件名只保留文件夹层级
processPath: function (inputPath) {
return path.dirname(inputPath);
},
};
// 以ES6模块格式导出这个包含所有工具方法的对象
export default ssh2Utils;