-
Notifications
You must be signed in to change notification settings - Fork 283
Expand file tree
/
Copy pathftp-test.js
More file actions
281 lines (239 loc) · 10.6 KB
/
ftp-test.js
File metadata and controls
281 lines (239 loc) · 10.6 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/**
* FTP 客户端测试文件
*
* 该文件用于测试 FTP 客户端的各种功能,包括:
* - 连接测试
* - 目录列表
* - 文件信息获取
* - 文件上传下载
* - 文件流获取(用于直链服务)
* - 目录创建和删除
*
* 使用方法:
* node ftp-test.js
*/
import { FTPClient } from '../utils/ftp.js';
import fs from 'fs';
import path from 'path';
// FTP 配置 - 请根据实际情况修改
const FTP_CONFIG = {
host: 'ftp.example.com',
port: 21,
username: 'testuser',
password: 'testpass',
secure: false,
pasv: true,
timeout: 30000,
verbose: true
};
/**
* 从配置文件加载 FTP 配置
*/
function loadFTPConfig() {
try {
// 直接读取指定的配置文件路径
const configPath = 'e:\\gitwork\\drpy-node\\json\\ftp.json';
if (fs.existsSync(configPath)) {
const configData = fs.readFileSync(configPath, 'utf8');
const config = JSON.parse(configData);
// 如果配置是数组格式,取第一个元素
let ftpConfig = Array.isArray(config) ? (config.length > 0 ? config[0] : null) : config;
if (ftpConfig) {
// 支持匿名 FTP 访问
if (!ftpConfig.username || ftpConfig.username === 'your-username' || ftpConfig.username === '') {
ftpConfig.username = 'anonymous';
}
if (!ftpConfig.password || ftpConfig.password === 'your-password' || ftpConfig.password === '') {
ftpConfig.password = 'anonymous@example.com';
}
}
return ftpConfig;
} else {
console.warn(`配置文件不存在: ${configPath}`);
}
} catch (error) {
console.warn('Failed to load FTP config from e:\\gitwork\\drpy-node\\json\\ftp.json:', error.message);
}
return FTP_CONFIG;
}
/**
* 运行 FTP 客户端测试
*/
async function runFTPTests() {
console.log('🚀 开始 FTP 客户端功能测试...\n');
const config = loadFTPConfig();
if (!config) {
console.error('❌ 无法加载 FTP 配置');
return;
}
console.log('📋 FTP 配置信息:');
console.log(` 主机: ${config.host}:${config.port}`);
console.log(` 用户: ${config.username}`);
console.log(` 安全: ${config.secure ? 'FTPS' : 'FTP'}`);
console.log(` 模式: ${config.pasv ? '被动' : '主动'}\n`);
const client = new FTPClient(config);
try {
// 1. 测试连接
console.log('🔗 测试 FTP 连接...');
const connected = await client.testConnection();
if (connected) {
console.log('✅ FTP 连接成功\n');
} else {
console.log('❌ FTP 连接失败\n');
return;
}
// 2. 测试目录列表
console.log('📁 测试目录列表功能...');
try {
const files = await client.listDirectory('/');
console.log(`✅ 目录列表获取成功,共 ${files.length} 个项目:`);
files.slice(0, 5).forEach(file => {
const type = file.isDirectory ? '📁' : '📄';
const size = file.isFile ? ` (${file.size} bytes)` : '';
console.log(` ${type} ${file.name}${size}`);
});
if (files.length > 5) {
console.log(` ... 还有 ${files.length - 5} 个项目`);
}
console.log();
} catch (error) {
console.log('❌ 目录列表获取失败:', error.message, '\n');
}
// 3. 测试文件信息获取
console.log('ℹ️ 测试文件信息获取...');
try {
const files = await client.listDirectory('/');
const testFile = files.find(f => f.isFile);
if (testFile) {
const fileInfo = await client.getInfo(testFile.path);
console.log('✅ 文件信息获取成功:');
console.log(` 文件名: ${fileInfo.name}`);
console.log(` 大小: ${fileInfo.size} bytes`);
console.log(` 类型: ${fileInfo.contentType}`);
console.log(` 修改时间: ${fileInfo.lastModified}`);
console.log();
} else {
console.log('⚠️ 根目录中没有找到文件,跳过文件信息测试\n');
}
} catch (error) {
console.log('❌ 文件信息获取失败:', error.message, '\n');
}
// 4. 测试文件存在性检查
console.log('🔍 测试文件存在性检查...');
try {
const exists1 = await client.exists('/');
const exists2 = await client.exists('/nonexistent-file-12345.txt');
console.log(`✅ 根目录存在: ${exists1}`);
console.log(`✅ 不存在的文件: ${exists2}\n`);
} catch (error) {
console.log('❌ 文件存在性检查失败:', error.message, '\n');
}
// 5. 测试目录创建和删除
console.log('📁 测试目录创建和删除...');
try {
const testDir = '/test-ftp-client-' + Date.now();
// 创建目录
await client.createDirectory(testDir);
console.log(`✅ 目录创建成功: ${testDir}`);
// 验证目录存在
const dirExists = await client.exists(testDir);
console.log(`✅ 目录存在验证: ${dirExists}`);
// 删除目录
await client.delete(testDir);
console.log(`✅ 目录删除成功: ${testDir}`);
// 验证目录不存在
const dirNotExists = await client.exists(testDir);
console.log(`✅ 目录删除验证: ${!dirNotExists}\n`);
} catch (error) {
console.log('❌ 目录操作失败:', error.message, '\n');
}
// 6. 测试文件上传和下载
console.log('📤 测试文件上传和下载...');
try {
const testContent = `FTP 客户端测试文件\n创建时间: ${new Date().toISOString()}\n随机数: ${Math.random()}`;
const testFileName = '/test-ftp-upload-' + Date.now() + '.txt';
// 上传文件
await client.putFileContent(testFileName, testContent);
console.log(`✅ 文件上传成功: ${testFileName}`);
// 下载文件
const downloadedContent = await client.getFileContent(testFileName);
console.log(`✅ 文件下载成功,内容匹配: ${downloadedContent === testContent}`);
// 删除测试文件
await client.delete(testFileName);
console.log(`✅ 测试文件删除成功\n`);
} catch (error) {
console.log('❌ 文件上传下载失败:', error.message, '\n');
}
// 7. 测试文件流获取(用于直链服务)
console.log('🌊 测试文件流获取功能...');
try {
const files = await client.listDirectory('/');
const testFile = files.find(f => f.isFile && f.size > 0 && f.size < 1024 * 1024); // 找一个小于1MB的文件
if (testFile) {
const streamInfo = await client.getFileStream(testFile.path);
console.log('✅ 文件流获取成功:');
console.log(` 文件: ${testFile.name}`);
console.log(` 大小: ${streamInfo.size} bytes`);
console.log(` 类型: ${streamInfo.contentType}`);
console.log(` Headers:`, Object.keys(streamInfo.headers).join(', '));
// 读取流的前几个字节来验证
let bytesRead = 0;
await new Promise((resolve, reject) => {
streamInfo.stream.on('data', (chunk) => {
bytesRead += chunk.length;
});
streamInfo.stream.on('end', () => {
console.log(`✅ 流读取完成,共读取 ${bytesRead} bytes\n`);
resolve();
});
streamInfo.stream.on('error', (error) => {
console.log('❌ 流读取错误:', error.message, '\n');
reject(error);
});
});
} else {
console.log('⚠️ 没有找到合适的测试文件,跳过文件流测试\n');
}
} catch (error) {
console.log('❌ 文件流获取失败:', error.message, '\n');
}
// 8. 测试文件移动/重命名
console.log('🔄 测试文件移动/重命名...');
try {
// 等待一下确保之前的操作完成
await new Promise(resolve => setTimeout(resolve, 1000));
const testContent = `移动测试文件\n时间: ${new Date().toISOString()}`;
const originalName = '/test-move-original-' + Date.now() + '.txt';
const newName = '/test-move-renamed-' + Date.now() + '.txt';
// 创建测试文件
await client.putFileContent(originalName, testContent);
console.log(`✅ 创建测试文件: ${originalName}`);
// 移动/重命名文件
await client.move(originalName, newName);
console.log(`✅ 文件重命名成功: ${originalName} -> ${newName}`);
// 验证原文件不存在,新文件存在
const originalExists = await client.exists(originalName);
const newExists = await client.exists(newName);
console.log(`✅ 原文件不存在: ${!originalExists}, 新文件存在: ${newExists}`);
// 清理测试文件
if (newExists) {
await client.delete(newName);
console.log(`✅ 清理测试文件成功\n`);
}
} catch (error) {
console.log('❌ 文件移动测试失败:', error.message, '\n');
}
console.log('🎉 FTP 客户端测试完成!');
} catch (error) {
console.error('❌ 测试过程中发生错误:', error.message);
} finally {
// 断开连接
await client.disconnect();
console.log('🔌 FTP 连接已断开');
}
}
// 主程序
if (import.meta.url.endsWith(process.argv[1].replace(/\\/g, '/'))) {
runFTPTests().catch(console.error);
}
export { runFTPTests, loadFTPConfig };