Files
AIclinicalresearch/backend/scripts/test-oss.ts

164 lines
5.6 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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)