/** * OSS存储适配器测试脚本 * * 使用方法: * 1. 配置环境变量(.env 文件) * 2. 运行:npx tsx scripts/test-oss.ts * * 测试项: * - 上传文件(按 MVP 目录结构) * - 下载文件 * - 检查文件存在 * - 获取签名URL * - 【可选】删除文件 */ import dotenv from 'dotenv' import path from 'path' import fs from 'fs' import { fileURLToPath } from 'url' import { randomUUID } from 'crypto' const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) // 加载环境变量 dotenv.config({ path: path.join(__dirname, '../.env') }) import { StorageFactory } from '../src/common/storage/StorageFactory.js' /** * 生成存储 Key(按 MVP 目录结构) * * 格式:tenants/{tenantId}/users/{userId}/{module}/{uuid}.{ext} */ function generateStorageKey( tenantId: string, userId: string | null, module: string, filename: string ): string { const uuid = randomUUID().replace(/-/g, '').substring(0, 16) const ext = path.extname(filename) if (userId) { // 用户私有数据 return `tenants/${tenantId}/users/${userId}/${module}/${uuid}${ext}` } else { // 租户共享数据 return `tenants/${tenantId}/shared/${module}/${uuid}${ext}` } } async function main() { console.log('='.repeat(60)) console.log('OSS 存储适配器测试 - MVP 目录结构验证') console.log('='.repeat(60)) // 检查环境变量 const storageType = process.env.STORAGE_TYPE || 'local' console.log(`\n📦 存储类型: ${storageType}`) if (storageType === 'oss') { console.log(` Region: ${process.env.OSS_REGION}`) console.log(` Bucket: ${process.env.OSS_BUCKET}`) console.log(` Internal: ${process.env.OSS_INTERNAL}`) } // 获取存储实例 const storage = StorageFactory.getInstance() console.log(`\n✅ 存储实例创建成功`) // ============================================================ // 测试文件:真实 PDF 文献 // ============================================================ const testPdfPath = path.join(__dirname, '../../docs/06-测试文档/Ihl 2011.pdf') if (!fs.existsSync(testPdfPath)) { console.error(`\n❌ 测试文件不存在: ${testPdfPath}`) process.exit(1) } const pdfBuffer = fs.readFileSync(testPdfPath) console.log(`\n📄 测试文件: Ihl 2011.pdf`) console.log(` 大小: ${(pdfBuffer.length / 1024).toFixed(2)} KB`) // ============================================================ // 按 MVP 目录结构生成 Key // ============================================================ // 模拟:租户 yizhengxun,用户 test-user-001,模块 pkb const tenantId = 'yizhengxun' const userId = 'test-user-001' const module = 'pkb' const storageKey = generateStorageKey(tenantId, userId, module, 'Ihl 2011.pdf') console.log(`\n📁 目录结构验证:`) console.log(` 租户ID: ${tenantId}`) console.log(` 用户ID: ${userId}`) console.log(` 模块: ${module}`) console.log(` 生成Key: ${storageKey}`) try { // 1. 上传测试 console.log(`\n📤 上传文件到 OSS...`) const uploadUrl = await storage.upload(storageKey, pdfBuffer) console.log(` ✅ 上传成功!`) console.log(` 签名URL: ${uploadUrl.substring(0, 80)}...`) // 2. 检查存在 console.log(`\n🔍 验证文件存在...`) const exists = await storage.exists(storageKey) console.log(` 存在: ${exists ? '✅ 是' : '❌ 否'}`) // 3. 下载验证 console.log(`\n📥 下载验证...`) const downloadBuffer = await storage.download(storageKey) const sizeMatch = downloadBuffer.length === pdfBuffer.length console.log(` 下载大小: ${(downloadBuffer.length / 1024).toFixed(2)} KB`) console.log(` 大小匹配: ${sizeMatch ? '✅ 是' : '❌ 否'}`) // 4. 获取URL(不带原始文件名) console.log(`\n🔗 获取访问URL...`) const url = storage.getUrl(storageKey) console.log(` URL: ${url.substring(0, 80)}...`) // 5. 获取URL(带原始文件名 - 下载时恢复文件名) console.log(`\n📎 获取带原始文件名的URL...`) // 类型断言访问 OSSAdapter 的 getSignedUrl 方法 const ossAdapter = storage as any if (typeof ossAdapter.getSignedUrl === 'function') { const urlWithFilename = ossAdapter.getSignedUrl(storageKey, 3600, 'Ihl 2011.pdf') console.log(` 原始文件名: Ihl 2011.pdf`) console.log(` URL: ${urlWithFilename.substring(0, 80)}...`) console.log(` ✅ 下载此URL时,浏览器会保存为 "Ihl 2011.pdf"`) } // ============================================================ // 🔴 不删除文件!保留在 OSS 中供验证 // ============================================================ console.log(`\n⚠️ 文件已保留在 OSS 中,不删除!`) console.log(` 请登录阿里云 OSS 控制台查看:`) console.log(` https://oss.console.aliyun.com/bucket/oss-cn-beijing/ai-clinical-data-dev/object`) console.log(`\n 文件路径: ${storageKey}`) // 测试完成 console.log('\n' + '='.repeat(60)) console.log('🎉 测试完成!请到 OSS 控制台验证目录结构') console.log('='.repeat(60)) // 输出完整信息供验证 console.log(`\n📋 验证信息:`) console.log(` Bucket: ai-clinical-data-dev`) console.log(` Key: ${storageKey}`) console.log(` 预期目录: tenants/yizhengxun/users/test-user-001/pkb/`) } catch (error) { console.error('\n❌ 测试失败:', error) process.exit(1) } } // 运行测试 main().catch(console.error)