269 lines
8.2 KiB
JavaScript
269 lines
8.2 KiB
JavaScript
|
|
const http = require('http');
|
|||
|
|
const https = require('https');
|
|||
|
|
|
|||
|
|
const BASE_URL = 'http://localhost:3000';
|
|||
|
|
const PASSWORD = 'wzw20040525';
|
|||
|
|
const CHUNK_SIZE = 5 * 1024 * 1024;
|
|||
|
|
|
|||
|
|
function request(options, body = null) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const url = new URL(options.path, BASE_URL);
|
|||
|
|
url.searchParams.set('password', PASSWORD);
|
|||
|
|
|
|||
|
|
const client = url.protocol === 'https:' ? https : http;
|
|||
|
|
|
|||
|
|
const reqOptions = {
|
|||
|
|
hostname: url.hostname,
|
|||
|
|
port: url.port,
|
|||
|
|
path: url.pathname + url.search,
|
|||
|
|
method: options.method,
|
|||
|
|
headers: options.headers || {}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const req = client.request(reqOptions, (res) => {
|
|||
|
|
let data = '';
|
|||
|
|
res.on('data', chunk => data += chunk);
|
|||
|
|
res.on('end', () => {
|
|||
|
|
try {
|
|||
|
|
resolve({ status: res.statusCode, data: JSON.parse(data) });
|
|||
|
|
} catch {
|
|||
|
|
resolve({ status: res.statusCode, data });
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
req.on('error', reject);
|
|||
|
|
|
|||
|
|
if (body) {
|
|||
|
|
if (body instanceof FormData) {
|
|||
|
|
req.write(body.getBuffer());
|
|||
|
|
} else if (Buffer.isBuffer(body)) {
|
|||
|
|
req.write(body);
|
|||
|
|
} else {
|
|||
|
|
req.write(JSON.stringify(body));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
req.end();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function testGetDrives() {
|
|||
|
|
console.log('\n=== 测试1: 获取驱动器列表 ===');
|
|||
|
|
try {
|
|||
|
|
const driveUrl = new URL('/api/files/browse', BASE_URL);
|
|||
|
|
driveUrl.searchParams.set('allowSystem', 'true');
|
|||
|
|
driveUrl.searchParams.set('password', PASSWORD);
|
|||
|
|
|
|||
|
|
const res = await request({
|
|||
|
|
method: 'GET',
|
|||
|
|
path: driveUrl.pathname + driveUrl.search
|
|||
|
|
});
|
|||
|
|
console.log('状态:', res.status);
|
|||
|
|
console.log('currentPath:', res.data.currentPath);
|
|||
|
|
console.log('parentPath:', res.data.parentPath);
|
|||
|
|
|
|||
|
|
// 检查是否返回了驱动器(盘符如 C:, D:)
|
|||
|
|
const drives = res.data.items?.filter(item => item.name.match(/^[A-Z]:$/i));
|
|||
|
|
if (drives && drives.length > 0) {
|
|||
|
|
console.log('✓ 驱动器列表:', drives.map(d => d.name).join(', '));
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果返回的是目录列表而非驱动器,说明 allowSystem 未生效
|
|||
|
|
console.log('✗ 未获取到驱动器列表');
|
|||
|
|
console.log('返回的项目:', res.data.items?.slice(0, 5).map(i => i.name).join(', '));
|
|||
|
|
return false;
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error('错误:', err.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function testUploadToSystemDir() {
|
|||
|
|
console.log('\n=== 测试2: 上传到系统目录 ===');
|
|||
|
|
const testContent = 'Hello Remote System Directory Test ' + Date.now();
|
|||
|
|
const filename = 'D:\\xc_test_file.txt';
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 1. 开始上传
|
|||
|
|
console.log('1. 开始上传...');
|
|||
|
|
const startUrl = new URL('/api/files/upload/start', BASE_URL);
|
|||
|
|
startUrl.searchParams.set('password', PASSWORD);
|
|||
|
|
|
|||
|
|
const startRes = await new Promise((resolve, reject) => {
|
|||
|
|
const req = http.request({
|
|||
|
|
hostname: startUrl.hostname,
|
|||
|
|
port: startUrl.port,
|
|||
|
|
path: startUrl.pathname + startUrl.search,
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: { 'Content-Type': 'application/json' }
|
|||
|
|
}, (res) => {
|
|||
|
|
let data = '';
|
|||
|
|
res.on('data', chunk => data += chunk);
|
|||
|
|
res.on('end', () => {
|
|||
|
|
try { resolve({ status: res.statusCode, data: JSON.parse(data) }); }
|
|||
|
|
catch { resolve({ status: res.statusCode, data }); }
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
req.on('error', reject);
|
|||
|
|
req.write(JSON.stringify({
|
|||
|
|
filename: filename,
|
|||
|
|
totalChunks: 1,
|
|||
|
|
fileSize: Buffer.byteLength(testContent)
|
|||
|
|
}));
|
|||
|
|
req.end();
|
|||
|
|
});
|
|||
|
|
console.log('开始上传响应:', startRes.data);
|
|||
|
|
|
|||
|
|
if (!startRes.data.fileId) {
|
|||
|
|
console.error('未获取到fileId');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const fileId = startRes.data.fileId;
|
|||
|
|
|
|||
|
|
// 2. 上传分块
|
|||
|
|
console.log('2. 上传分块...');
|
|||
|
|
const chunk = Buffer.from(testContent);
|
|||
|
|
|
|||
|
|
const chunkUrl = new URL('/api/files/upload/chunk', BASE_URL);
|
|||
|
|
chunkUrl.searchParams.set('password', PASSWORD);
|
|||
|
|
|
|||
|
|
const FormData = require('form-data');
|
|||
|
|
const form = new FormData();
|
|||
|
|
form.append('fileId', fileId);
|
|||
|
|
form.append('chunkIndex', '0');
|
|||
|
|
form.append('chunk', chunk, { filename: 'chunk', contentType: 'application/octet-stream' });
|
|||
|
|
|
|||
|
|
const chunkRes = await new Promise((resolve, reject) => {
|
|||
|
|
const req = http.request({
|
|||
|
|
hostname: chunkUrl.hostname,
|
|||
|
|
port: chunkUrl.port,
|
|||
|
|
path: chunkUrl.pathname + chunkUrl.search,
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: form.getHeaders()
|
|||
|
|
}, (res) => {
|
|||
|
|
let data = '';
|
|||
|
|
res.on('data', c => data += c);
|
|||
|
|
res.on('end', () => {
|
|||
|
|
try { resolve({ status: res.statusCode, data: JSON.parse(data) }); }
|
|||
|
|
catch { resolve({ status: res.statusCode, data }); }
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
req.on('error', reject);
|
|||
|
|
req.write(form.getBuffer());
|
|||
|
|
req.end();
|
|||
|
|
});
|
|||
|
|
console.log('分块上传响应:', chunkRes.data);
|
|||
|
|
|
|||
|
|
// 3. 合并文件
|
|||
|
|
console.log('3. 合并文件...');
|
|||
|
|
const mergeUrl = new URL('/api/files/upload/merge', BASE_URL);
|
|||
|
|
mergeUrl.searchParams.set('password', PASSWORD);
|
|||
|
|
|
|||
|
|
const mergeRes = await new Promise((resolve, reject) => {
|
|||
|
|
const req = http.request({
|
|||
|
|
hostname: mergeUrl.hostname,
|
|||
|
|
port: mergeUrl.port,
|
|||
|
|
path: mergeUrl.pathname + mergeUrl.search,
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: { 'Content-Type': 'application/json' }
|
|||
|
|
}, (res) => {
|
|||
|
|
let data = '';
|
|||
|
|
res.on('data', c => data += c);
|
|||
|
|
res.on('end', () => {
|
|||
|
|
try { resolve({ status: res.statusCode, data: JSON.parse(data) }); }
|
|||
|
|
catch { resolve({ status: res.statusCode, data }); }
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
req.on('error', reject);
|
|||
|
|
req.write(JSON.stringify({
|
|||
|
|
fileId: fileId,
|
|||
|
|
totalChunks: 1,
|
|||
|
|
filename: filename
|
|||
|
|
}));
|
|||
|
|
req.end();
|
|||
|
|
});
|
|||
|
|
console.log('合并响应:', mergeRes.data);
|
|||
|
|
|
|||
|
|
return mergeRes.data.success === true;
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error('错误:', err.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function testDownloadFromSystemDir() {
|
|||
|
|
console.log('\n=== 测试3: 从系统目录下载 ===');
|
|||
|
|
const filename = 'D:\\xc_test_file.txt';
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const encodedPath = encodeURIComponent(filename);
|
|||
|
|
const res = await request({
|
|||
|
|
method: 'GET',
|
|||
|
|
path: `/api/files/${encodedPath}`
|
|||
|
|
});
|
|||
|
|
console.log('状态:', res.status);
|
|||
|
|
console.log('响应类型:', typeof res.data);
|
|||
|
|
return res.status === 200;
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error('错误:', err.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function testDeleteFile() {
|
|||
|
|
console.log('\n=== 测试4: 删除测试文件 ===');
|
|||
|
|
const filename = 'D:\\xc_test_file.txt';
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const encodedPath = encodeURIComponent(filename);
|
|||
|
|
const res = await request({
|
|||
|
|
method: 'DELETE',
|
|||
|
|
path: `/api/files/${encodedPath}`
|
|||
|
|
});
|
|||
|
|
console.log('状态:', res.status);
|
|||
|
|
console.log('响应:', res.data);
|
|||
|
|
return res.data.success === true || res.status === 200;
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error('错误:', err.message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function main() {
|
|||
|
|
console.log('========================================');
|
|||
|
|
console.log('远程文件传输功能测试');
|
|||
|
|
console.log('目标服务器: 146.56.248.142:8080');
|
|||
|
|
console.log('========================================');
|
|||
|
|
|
|||
|
|
const results = [];
|
|||
|
|
|
|||
|
|
// 测试1: 获取驱动器列表
|
|||
|
|
results.push({ name: '获取驱动器列表', pass: await testGetDrives() });
|
|||
|
|
|
|||
|
|
// 测试2: 上传到系统目录
|
|||
|
|
results.push({ name: '上传到系统目录', pass: await testUploadToSystemDir() });
|
|||
|
|
|
|||
|
|
// 测试3: 从系统目录下载
|
|||
|
|
results.push({ name: '从系统目录下载', pass: await testDownloadFromSystemDir() });
|
|||
|
|
|
|||
|
|
// 测试4: 删除测试文件
|
|||
|
|
results.push({ name: '删除测试文件', pass: await testDeleteFile() });
|
|||
|
|
|
|||
|
|
// 汇总结果
|
|||
|
|
console.log('\n========================================');
|
|||
|
|
console.log('测试结果汇总:');
|
|||
|
|
console.log('========================================');
|
|||
|
|
results.forEach(r => {
|
|||
|
|
console.log(`${r.pass ? '✓' : '✗'} ${r.name}`);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const allPass = results.every(r => r.pass);
|
|||
|
|
console.log(`\n总体结果: ${allPass ? '全部通过' : '存在失败'}`);
|
|||
|
|
process.exit(allPass ? 0 : 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
main();
|