kdofficial/scripts/uploadAssets2volOSS.ts
2025-08-21 18:26:35 +08:00

131 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

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.

// Access Key ID Secret Access Key
// AKLTZDY5ZjE0ZjMxODdiNDhjODkyYzhkODY2MmUwYmZlMzc TjJaak5XVTBOR0ZtTTJRek5HWTRPRGhoT0RBellXUTNORFV3WmpOa1pERQ==
// S3 endpointtos-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';
import { fileURLToPath } from 'url';
// 配置信息
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<string, string> = {
'.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<string[]> {
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<void> {
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<void> {
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() {
// ES 模块中获取当前文件目录的正确方式
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const assetsDir = path.resolve(__dirname, '../dist/assets');
console.log(`开始上传目录: ${assetsDir}`);
await uploadDirectory(assetsDir);
}
// 执行主函数
main().catch(error => {
console.error('程序执行失败:', error);
process.exit(1);
});