// Access Key ID Secret Access Key // AKLTZDY5ZjE0ZjMxODdiNDhjODkyYzhkODY2MmUwYmZlMzc TjJaak5XVTBOR0ZtTTJRek5HWTRPRGhoT0RBellXUTNORFV3WmpOa1pERQ== // S3 endpoint:tos-cn-beijing.volces.com // 外网访问:tos-s3-cn-beijing.volces.com // Bucket 域名:kdesign-offical.tos-cn-beijing.volces.com import { TosClient } from '@volcengine/tos-sdk'; import * as fs from 'fs'; import * as path from 'path'; // 配置信息 const config = { accessKeyId: 'AKLTZDY5ZjE0ZjMxODdiNDhjODkyYzhkODY2MmUwYmZlMzc', secretAccessKey: 'TjJaak5XVTBOR0ZtTTJRek5HWTRPRGhoT0RBellXUTNORFV3WmpOa1pERQ==', endpoint: 'tos-cn-beijing.volces.com', region: 'cn-beijing', bucket: 'kdesign-offical' }; // 创建 TOS 客户端 const client = new TosClient({ accessKeyId: config.accessKeyId, accessKeySecret: config.secretAccessKey, endpoint: config.endpoint, region: config.region }); // 获取文件的 Content-Type function getContentType(filePath: string): string { const ext = path.extname(filePath).toLowerCase(); const contentTypeMap: Record = { '.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript', '.json': 'application/json', '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.mp4': 'video/mp4', '.webp': 'image/webp', '.ico': 'image/x-icon', '.txt': 'text/plain', '.pdf': 'application/pdf', '.zip': 'application/zip' }; return contentTypeMap[ext] || 'application/octet-stream'; } // 递归获取目录下所有文件 async function getAllFiles(dirPath: string, fileList: string[] = []): Promise { const files = fs.readdirSync(dirPath); for (const file of files) { const filePath = path.join(dirPath, file); const stat = fs.statSync(filePath); if (stat.isDirectory()) { await getAllFiles(filePath, fileList); } else { fileList.push(filePath); } } return fileList; } // 上传单个文件 async function uploadFile(filePath: string, basePath: string): Promise { try { // 计算相对路径作为对象键名 const key = filePath.replace(basePath, '').replace(/^\//, ''); const contentType = getContentType(filePath); const fileContent = fs.readFileSync(filePath); console.log(`上传文件: ${filePath} -> ${key}`); const response = await client.putObject({ bucket: config.bucket, key: key, body: fileContent, contentType: contentType }); console.log(`上传成功: ${key}, 请求ID: ${response.requestId}`); } catch (error) { console.error(`上传文件 ${filePath} 失败:`, error); } } // 上传目录下所有文件 async function uploadDirectory(dirPath: string): Promise { try { const basePath = path.resolve(dirPath, '..'); const allFiles = await getAllFiles(dirPath); console.log(`找到 ${allFiles.length} 个文件需要上传`); // 创建上传任务队列 const uploadTasks = allFiles.map(filePath => uploadFile(filePath, basePath)); // 并发上传文件 await Promise.all(uploadTasks); console.log('所有文件上传完成'); } catch (error) { console.error('上传目录失败:', error); } } // 主函数 async function main() { // 使用 import.meta.url 替代 __dirname (ES 模块兼容) const currentFileUrl = import.meta.url; const currentFilePath = new URL(currentFileUrl).pathname; const currentDir = path.dirname(currentFilePath); const assetsDir = path.resolve(currentDir, '../dist/assets'); console.log(`开始上传目录: ${assetsDir}`); await uploadDirectory(assetsDir); } // 执行主函数 main().catch(error => { console.error('程序执行失败:', error); process.exit(1); });