262 lines
7.6 KiB
JavaScript
262 lines
7.6 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* MinIO配置测试脚本
|
||
* 基于用户提供的具体配置进行测试
|
||
*/
|
||
|
||
const { S3 } = require('@aws-sdk/client-s3');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
async function testMinIOConfig() {
|
||
console.log('🔍 开始测试MinIO配置...\n');
|
||
|
||
// 用户提供的配置
|
||
const config = {
|
||
endpoint: 'http://localhost:9000',
|
||
region: 'us-east-1',
|
||
credentials: {
|
||
accessKeyId: '7Nt7OyHkwIoo3zvSKdnc',
|
||
secretAccessKey: 'EZ0cyrjJAsabTLNSqWcU47LURMppBW2kka3LuXzb',
|
||
},
|
||
forcePathStyle: true,
|
||
};
|
||
|
||
const bucketName = 'test123';
|
||
const uploadDir = '/opt/projects/nice/uploads';
|
||
|
||
console.log('📋 配置信息:');
|
||
console.log(` Endpoint: ${config.endpoint}`);
|
||
console.log(` Region: ${config.region}`);
|
||
console.log(` Bucket: ${bucketName}`);
|
||
console.log(` Upload Dir: ${uploadDir}`);
|
||
console.log(` Access Key: ${config.credentials.accessKeyId}`);
|
||
console.log(` Force Path Style: ${config.forcePathStyle}`);
|
||
console.log();
|
||
|
||
try {
|
||
const s3Client = new S3(config);
|
||
|
||
// 1. 测试基本连接和认证
|
||
console.log('📡 测试连接和认证...');
|
||
try {
|
||
const buckets = await s3Client.listBuckets();
|
||
console.log('✅ 连接和认证成功!');
|
||
console.log(`📂 现有存储桶: ${buckets.Buckets?.map((b) => b.Name).join(', ') || '无'}`);
|
||
} catch (error) {
|
||
console.log('❌ 连接失败:', error.message);
|
||
if (error.message.includes('ECONNREFUSED')) {
|
||
console.log('💡 提示: MinIO服务可能未运行,请检查localhost:9000是否可访问');
|
||
} else if (error.message.includes('Invalid')) {
|
||
console.log('💡 提示: 检查访问密钥和密钥是否正确');
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// 2. 检查目标存储桶
|
||
console.log(`\n🪣 检查存储桶 "${bucketName}"...`);
|
||
let bucketExists = false;
|
||
try {
|
||
await s3Client.headBucket({ Bucket: bucketName });
|
||
console.log(`✅ 存储桶 "${bucketName}" 存在并可访问`);
|
||
bucketExists = true;
|
||
} catch (error) {
|
||
if (error.name === 'NotFound') {
|
||
console.log(`❌ 存储桶 "${bucketName}" 不存在`);
|
||
console.log('🔧 尝试创建存储桶...');
|
||
try {
|
||
await s3Client.createBucket({ Bucket: bucketName });
|
||
console.log(`✅ 存储桶 "${bucketName}" 创建成功`);
|
||
bucketExists = true;
|
||
} catch (createError) {
|
||
console.log(`❌ 创建存储桶失败: ${createError.message}`);
|
||
return false;
|
||
}
|
||
} else {
|
||
console.log(`❌ 检查存储桶时出错: ${error.message}`);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (!bucketExists) {
|
||
return false;
|
||
}
|
||
|
||
// 3. 检查上传目录
|
||
console.log(`\n📁 检查上传目录 "${uploadDir}"...`);
|
||
try {
|
||
if (!fs.existsSync(uploadDir)) {
|
||
console.log('📁 上传目录不存在,正在创建...');
|
||
fs.mkdirSync(uploadDir, { recursive: true });
|
||
console.log('✅ 上传目录创建成功');
|
||
} else {
|
||
console.log('✅ 上传目录存在');
|
||
}
|
||
} catch (error) {
|
||
console.log(`❌ 检查/创建上传目录失败: ${error.message}`);
|
||
}
|
||
|
||
// 4. 测试文件上传
|
||
console.log('\n📤 测试文件上传...');
|
||
const testFileName = `test-upload-${Date.now()}.txt`;
|
||
const testContent = `这是一个测试文件
|
||
创建时间: ${new Date().toISOString()}
|
||
用户: nice1234
|
||
MinIO测试成功!`;
|
||
|
||
try {
|
||
await s3Client.putObject({
|
||
Bucket: bucketName,
|
||
Key: testFileName,
|
||
Body: testContent,
|
||
ContentType: 'text/plain',
|
||
Metadata: {
|
||
'test-type': 'config-validation',
|
||
'created-by': 'test-script',
|
||
},
|
||
});
|
||
console.log(`✅ 文件上传成功: ${testFileName}`);
|
||
} catch (error) {
|
||
console.log(`❌ 文件上传失败: ${error.message}`);
|
||
console.log('错误详情:', error);
|
||
return false;
|
||
}
|
||
|
||
// 5. 测试文件下载验证
|
||
console.log('\n📥 测试文件下载验证...');
|
||
try {
|
||
const result = await s3Client.getObject({
|
||
Bucket: bucketName,
|
||
Key: testFileName,
|
||
});
|
||
|
||
// 读取流内容
|
||
const chunks = [];
|
||
for await (const chunk of result.Body) {
|
||
chunks.push(chunk);
|
||
}
|
||
const downloadedContent = Buffer.concat(chunks).toString();
|
||
|
||
if (downloadedContent === testContent) {
|
||
console.log('✅ 文件下载验证成功,内容一致');
|
||
} else {
|
||
console.log('❌ 文件内容不一致');
|
||
return false;
|
||
}
|
||
} catch (error) {
|
||
console.log(`❌ 文件下载失败: ${error.message}`);
|
||
return false;
|
||
}
|
||
|
||
// 6. 测试分片上传
|
||
console.log('\n🔄 测试分片上传功能...');
|
||
const multipartKey = `multipart-test-${Date.now()}.dat`;
|
||
try {
|
||
const multipartUpload = await s3Client.createMultipartUpload({
|
||
Bucket: bucketName,
|
||
Key: multipartKey,
|
||
Metadata: {
|
||
'test-type': 'multipart-upload',
|
||
},
|
||
});
|
||
console.log(`✅ 分片上传初始化成功: ${multipartUpload.UploadId}`);
|
||
|
||
// 清理测试
|
||
await s3Client.abortMultipartUpload({
|
||
Bucket: bucketName,
|
||
Key: multipartKey,
|
||
UploadId: multipartUpload.UploadId,
|
||
});
|
||
console.log('✅ 分片上传测试完成并清理');
|
||
} catch (error) {
|
||
console.log(`❌ 分片上传测试失败: ${error.message}`);
|
||
return false;
|
||
}
|
||
|
||
// 7. 列出存储桶中的文件
|
||
console.log('\n📂 列出存储桶中的文件...');
|
||
try {
|
||
const listResult = await s3Client.listObjectsV2({
|
||
Bucket: bucketName,
|
||
MaxKeys: 10,
|
||
});
|
||
|
||
console.log(`✅ 存储桶中共有 ${listResult.KeyCount || 0} 个文件`);
|
||
if (listResult.Contents && listResult.Contents.length > 0) {
|
||
console.log('最近的文件:');
|
||
listResult.Contents.slice(-5).forEach((obj, index) => {
|
||
const size = obj.Size < 1024 ? `${obj.Size}B` : `${Math.round(obj.Size / 1024)}KB`;
|
||
console.log(` ${index + 1}. ${obj.Key} (${size})`);
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.log(`❌ 列出文件失败: ${error.message}`);
|
||
}
|
||
|
||
// 8. 清理测试文件
|
||
console.log('\n🧹 清理测试文件...');
|
||
try {
|
||
await s3Client.deleteObject({
|
||
Bucket: bucketName,
|
||
Key: testFileName,
|
||
});
|
||
console.log('✅ 测试文件清理完成');
|
||
} catch (error) {
|
||
console.log(`⚠️ 清理测试文件失败: ${error.message}`);
|
||
}
|
||
|
||
console.log('\n🎉 所有测试通过!您的MinIO配置完全正确!');
|
||
console.log('\n📝 配置摘要:');
|
||
console.log('- ✅ 连接正常');
|
||
console.log('- ✅ 认证有效');
|
||
console.log('- ✅ 存储桶可用');
|
||
console.log('- ✅ 文件上传/下载正常');
|
||
console.log('- ✅ 分片上传支持');
|
||
console.log('\n💡 您可以在应用中使用这些配置:');
|
||
console.log('STORAGE_TYPE=s3');
|
||
console.log(`UPLOAD_DIR=${uploadDir}`);
|
||
console.log(`S3_ENDPOINT=${config.endpoint}`);
|
||
console.log(`S3_REGION=${config.region}`);
|
||
console.log(`S3_BUCKET=${bucketName}`);
|
||
console.log(`S3_ACCESS_KEY_ID=${config.credentials.accessKeyId}`);
|
||
console.log('S3_SECRET_ACCESS_KEY=***');
|
||
console.log('S3_FORCE_PATH_STYLE=true');
|
||
|
||
return true;
|
||
} catch (error) {
|
||
console.log(`❌ 测试过程中发生未预期错误: ${error.message}`);
|
||
console.log('错误堆栈:', error.stack);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 主函数
|
||
async function main() {
|
||
console.log('🚀 MinIO S3存储配置测试\n');
|
||
|
||
// 检查依赖
|
||
try {
|
||
require('@aws-sdk/client-s3');
|
||
} catch (error) {
|
||
console.log('❌ 缺少必要依赖 @aws-sdk/client-s3');
|
||
console.log('请运行: npm install @aws-sdk/client-s3');
|
||
process.exit(1);
|
||
}
|
||
|
||
const success = await testMinIOConfig();
|
||
|
||
if (success) {
|
||
console.log('\n✅ 测试完成:MinIO配置正确,可以正常使用!');
|
||
process.exit(0);
|
||
} else {
|
||
console.log('\n❌ 测试失败:请检查上述错误并修复配置');
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
main().catch((error) => {
|
||
console.error('❌ 脚本执行失败:', error);
|
||
process.exit(1);
|
||
});
|