自动化腾讯云 COS 迁移助手
通过自然语言对话,将阿里云 OSS 对象存储数据迁移到腾讯云 COS。
🎯 核心特性
- 💬 对话式交互: 通过自然对话收集凭证、选择资源
- 📂 资源浏览: 自动列出OSS和COS存储桶供选择
- 🤖 自动化迁移: 一键创建MSP迁移任务
- 📊 任务管理: 查看任务状态和基本进度信息
- 🛡️ 基础安全: 凭证脱敏显示,日志记录保护
- 📋 迁移报告: 任务完成后生成基本统计报告
🚀 触发关键词
当用户提到以下关键词时触发此技能:
- "迁移 OSS 到 COS"
- "阿里云迁移到腾讯云"
- "云存储迁移"
- "COS 迁移"
- "OSS 迁移"
- "跨云迁移"
💡 支持的功能
1. 配置凭证
配置阿里云 OSS 和腾讯云 COS 的访问凭证。
表达方式:
- "配置凭证"
- "设置密钥"
- "configure credentials"
2. 查看存储桶
列出阿里云 OSS 或腾讯云 COS 的存储桶。
表达方式:
- "查看我的桶"
- "列出存储桶"
- "查看 OSS 桶"
- "显示 COS 桶"
3. 查看文件列表
查看指定存储桶内的文件列表。
表达方式:
- "查看 xxhu-oss-hdfs 桶的文件"
- "查看 OSS 桶 my-bucket 里有什么文件"
- "列出 bucket-123 的文件"
- "看看 my-bucket 里面有什么"
- "桶里有什么文件"
注意: 需要先配置凭证,支持指定 OSS 或 COS provider。
4. 查看迁移参数
查看所有迁移任务参数及其默认值。
表达方式:
- "查看迁移参数"
- "有哪些参数"
- "显示所有参数"
- "迁移参数列表"
- "所有参数"
- "当前配置"
5. 创建迁移任务
创建单个迁移任务,从源桶迁移到目标桶。
表达方式:
- "从 bucket-a 迁移到 bucket-b"
- "开始迁移"
- "创建迁移任务"
- "数据迁移"
- "传输数据"
6. 批量创建迁移任务
从 Excel 文件批量创建多个迁移任务。
表达方式:
- "批量创建迁移任务"
- "从文件创建任务"
- "上传 Excel 创建任务"
- "批量迁移"
文件格式要求:
- 第1行:参数名称
- 第2行:参数说明
- 第3行开始:迁移任务数据
- 必需参数:JobName, SrcBucket, DstBucket
7. 查看任务状态
查看迁移任务的执行状态和进度。
表达方式:
- "查看任务状态"
- "任务进度如何"
- "查看迁移任务"
- "监控任务"
- "任务情况"
💬 对话式工作流程
场景 1: 首次使用(无凭证)
AI: 检测到你还没有配置云存储凭证。请提供:
📦 阿里云 OSS(源端):
1. AccessKey ID
2. AccessKey Secret
3. 区域(如 oss-cn-hangzhou)
用户: 我的 AccessKey ID 是 LTAI4***, Secret 是 abc***, 区域是 oss-cn-hangzhou
AI: ✅ 阿里云凭证已验证。请提供腾讯云凭证:
📦 腾讯云 COS(目标端):
1. Secret ID
2. Secret Key
3. 区域(如 ap-guangzhou)
用户: 我的 Secret ID 是 AKID***, Secret Key 是 ***
AI: ✅ 凭证已安全保存。正在列出你的存储桶...
📦 阿里云 OSS 存储桶:
1. my-images
2. my-logs
3. my-backup
请选择要迁移的源桶?
用户: 我想迁移 my-images
AI: 📦 腾讯云 COS 存储桶:
1. backup-bucket-1234567890
2. images-bucket-1234567890
请选择目标桶?
用户: 用 images-bucket-1234567890
AI: 📋 迁移配置确认:
源端: my-images
目标: images-bucket-1234567890
覆盖模式: 跳过同名文件
确认开始迁移? (是/否)
用户: 是
AI: 🚀 迁移任务已创建!
任务 ID: task-abc1234567890
使用以下命令查看任务状态:
cos-migrate status --task-id task-abc1234567890
场景 2: 已有凭证
用户: 帮我迁移 OSS 到 COS
AI: ✅ 检测到已保存的凭证。正在列出存储桶...
📦 阿里云 OSS 存储桶:
...
[继续选择流程]
场景 3: 查询任务进度
用户: 查看我的迁移任务进度
AI: 📋 迁移任务列表:
1. ✅ migration-20260330 (已完成)
源: my-images → 目标: images-bucket
2. 🔄 migration-20260331 (运行中)
源: my-logs → 目标: logs-bucket
输入任务 ID 查看详细信息
⚠️ 操作确认
以下操作需要二次确认:
| 操作 | 确认方式 | |------|----------| | 取消迁移任务 | 使用 --confirm 参数或确认提示
确认话术示例:
⚠️ **操作确认**
你即将执行: 取消迁移任务
任务 ID: task-abc1234567890
此操作将:
- 停止正在进行的迁移任务
- 已迁移的文件不会回滚
请添加 --confirm 参数来确认执行,或取消操作
🔒 安全机制
敏感信息处理
| 场景 | 处理方式 |
|------|----------|
| 用户输入 Secret | 脱敏显示,避免完整暴露 |
| 显示已保存凭证 | 脱敏显示: LTAI4***7890 |
| 日志安全 | 敏感信息记录时进行遮蔽处理 |
凭证存储
- 存储方式: 本地文件存储(建议用户自行确保文件安全)
- 日志文件:
~/.cos-migration/logs/migration-YYYY-MM-DD.log
📦 迁移模式
| 模式 | 说明 | 状态 | |------|------|------| | 全托管迁移 | MSP 通过公网从阿里云OSS拉取数据到腾讯云COS | ✅ 支持 | | 半托管迁移 | 在源端部署Agent推送数据(当前硬编码配置) | ⚠️ 实验性 |
注意: 当前版本主要支持全托管迁移模式。半托管模式需要额外的Agent部署配置。
🛠️ CLI 工具(可选)
除了对话式交互,也可以使用 CLI 工具:
# 安装依赖
cd {baseDir}
npm install
# 配置凭证
npm run dev config -- --show
# 列出存储桶
npm run dev list-buckets -- --oss
npm run dev list-buckets -- --cos
# 创建迁移任务
npm run dev migrate -- --source my-oss-bucket --target my-cos-bucket
# 查看任务状态
npm run dev status -- --task-id task-xxx
# 查看所有任务
npm run dev tasks
🛠️ 本工程客户端使用示例
本工程封装了 OSS、COS 和 MSP 客户端,提供统一的 API 接口。以下是各客户端的使用方法。
OSS 客户端(阿里云)
import { OSSClient } from './lib/oss-client';
/**
* 初始化 OSS 客户端
*/
const ossClient = new OSSClient(
accessKeyId, // 阿里云 AccessKeyID
accessKeySecret, // 阿里云 AccessKeySecret
region // 区域,如 'oss-cn-hangzhou'
// bucket // 可选:指定默认桶
);
/**
* 列出所有存储桶
*/
const buckets = await ossClient.listBuckets();
// 返回: BucketInfo[] { name, location, creationDate, storageClass }
/**
* 列出桶内文件
*/
const files = await ossClient.listFiles(bucketName, prefix);
// 返回: FileInfo[] { key, size, lastModified, etag, storageClass }
/**
* 获取桶统计信息
*/
const stats = await ossClient.getBucketStats(bucketName, prefix);
// 返回: BucketStats { fileCount, totalSize, lastModified }
/**
* 验证凭证是否有效
*/
const isValid = await ossClient.validateCredentials();
/**
* 获取文件签名 URL(用于直接下载)
*/
const url = await ossClient.getSignedUrl(bucketName, objectKey, expires);
COS 客户端(腾讯云)
import { COSClient } from './lib/cos-client';
/**
* 初始化 COS 客户端
*/
const cosClient = new COSClient(
secretId, // 腾讯云 SecretId
secretKey, // 腾讯云 SecretKey
region // 区域,如 'ap-guangzhou'
);
/**
* 列出所有存储桶
*/
const buckets = await cosClient.listBuckets();
// 返回: BucketInfo[] { name, location, creationDate, storageClass }
/**
* 列出桶内文件
*/
const files = await cosClient.listFiles(bucketName, prefix);
// 返回: FileInfo[] { key, size, lastModified, etag, storageClass }
/**
* 检查存储桶是否存在
*/
const exists = await cosClient.bucketExists(bucketName);
/**
* 获取桶统计信息
*/
const stats = await cosClient.getBucketStats(bucketName, prefix);
// 返回: BucketStats { fileCount, totalSize, lastModified }
/**
* 检查文件是否存在
*/
const fileExists = await cosClient.fileExists(bucketName, key);
/**
* 验证凭证是否有效
*/
const isValid = await cosClient.validateCredentials();
/**
* 删除文件(高危操作)
*/
await cosClient.deleteFile(bucketName, key);
/**
* 批量删除文件(高危操作)
*/
await cosClient.deleteFiles(bucketName, [key1, key2, ...]);
MSP 客户端(腾讯云迁移服务)
import { MSPClient } from './lib/msp-client';
/**
* 初始化 MSP 客户端
*/
const mspClient = new MSPClient({
secretId, // 腾讯云 SecretId
secretKey, // 腾讯云 SecretKey
region // 可选,默认调用 MSP API
});
/**
* 创建迁移任务
*/
const result = await mspClient.createMigrationTask({
JobName: 'migration-task-001',
SrcBucket: 'source-bucket',
DstBucket: 'target-bucket-1250000000',
SrcSecretId: aliyunAccessKeyId,
SrcSecretKey: aliyunAccessKeySecret,
DstSecretId: tencentSecretId,
DstSecretKey: tencentSecretKey,
// 可选参数
SrcService: 'OSS', // 默认 'OSS'
DstService: 'COS', // 默认 'COS'
FileOverWrite: 1, // 0=覆盖, 1=跳过,默认 1
StorageType: 3, // 存储类型,默认 3(保持原属性)
Mode: 0, // 0=全托管, 1=半托管,默认 0
HasFileTime: 0, // 是否时间过滤,默认 0
StartTime: '2025-01-01 00:00:00', // HasFileTime=1 时必需
EndTime: '2025-12-31 23:59:59' // HasFileTime=1 时必需
});
// 返回: { JobId: string, RequestId: string }
/**
* 查询任务列表
*/
const tasks = await mspClient.listTasks({
JobId: 'fm-xxx', // 可选:指定任务 ID
Offset: 0, // 可选:偏移量
Limit: 100 // 可选:限制数量
});
// 返回: MSPJobInfo[] { JobId, JobName, Status, StatusId, Progress, ... }
/**
* 查询任务详情
*/
const taskDetail = await mspClient.getTaskDetail(jobId);
// 返回: MSPJobInfo
/**
* 获取任务状态
*/
const status = await mspClient.getTaskStatus(jobId);
// 返回: { taskId, status, totalFiles, completedFiles, failedFiles, ... }
/**
* 获取迁移结果
*/
const result = await mspClient.getMigrationResult(jobId);
// 返回: { taskId, status, totalFiles, successFiles, failedFiles, ... }
/**
* 取消任务
*/
await mspClient.cancelTask(jobId);
/**
* 验证凭证是否有效
*/
const isValid = await mspClient.validateCredentials();
任务状态码对照
本工程的 MSPClient 使用以下状态映射:
| StatusId | 状态文本 | 本工程状态 | |----------|----------|-----------| | 1 | 等待中 | pending | | 2 | 扫描中 | running | | 3 | 迁移中 | running | | 4 | 校验中 | running | | 5 | 完成 | completed | | 6 | 失败 | failed | | 7 | 取消 | cancelled | | 8 | 等待中 | pending | | 9 | 任务完成 | completed |
参数依赖关系
某些参数之间存在依赖关系,配置时需要注意:
| 参数 | 依赖条件 | 说明 |
|------|----------|------|
| SavePath | SaveType=1 | 只有保存到指定目录时才需要 |
| FileStartTime / FileEndTime | HasFileTime=1 | 启用时间过滤时需要 |
| ListerIp / EndPoint | Mode=1 | 半托管模式必需 |
创建任务完整参数示例
以下是使用 MSPClient.createMigrationTask() 创建迁移任务的完整参数说明:
最小配置示例
await mspClient.createMigrationTask({
JobName: 'my-migration-task',
SrcBucket: 'my-source-bucket',
DstBucket: 'my-target-bucket-1250000000',
SrcSecretId: 'LTAI5txxxx',
SrcSecretKey: 'xxxxx',
DstSecretId: 'AKIDxxxxx',
DstSecretKey: 'xxxxx'
});
完整参数示例
await mspClient.createMigrationTask({
// ===== 基本信息 =====
JobName: 'aliyun-to-cos-migration-20250413',
// ===== 源端配置 =====
SrcBucket: 'my-source-bucket',
SrcSecretId: process.env.ALIYUN_OSS_ACCESS_KEY_ID,
SrcSecretKey: process.env.ALIYUN_OSS_ACCESS_KEY_SECRET,
SrcService: 'OSS', // 可选,默认 'OSS'
// ===== 目标端配置 =====
DstBucket: 'my-target-bucket-1250000000',
DstSecretId: process.env.TENCENT_COS_SECRET_ID,
DstSecretKey: process.env.TENCENT_COS_SECRET_KEY,
DstService: 'COS', // 可选,默认 'COS'
// ===== Header 迁移设置 =====
MigrationHeaderType: 1, // 1=保留全部,2=丢弃全部,3=自定义替换,默认 1
MigrationHeader: [ // MigrationHeaderType=3 时需要
{ origin: 'x-oss-meta-a', cos: 'x-cos-meta-a' }
],
// ===== 文件过滤规则 =====
MigrationRuleType: 1, // 1=不过滤,2=前缀匹配,3=正则匹配,默认 1
MigrationRule: ['images/', 'videos/'], // MigrationRuleType=2/3 时需要
// ===== 时间过滤 =====
HasFileTime: 1, // 0=不启用,1=启用,默认 0
StartTime: '2025-01-01 00:00:00', // HasFileTime=1 时必需
EndTime: '2025-12-31 23:59:59', // HasFileTime=1 时必需
// ===== 文件冲突处理 =====
FileOverWrite: 1, // 0=覆盖同名文件,1=跳过同名文件,默认 1
// ===== 目标存储类型 =====
StorageType: 3, // 1=标准,2=低频,3=保持原属性,4=归档,5=智能分层,6=冷存储,默认 3
// ===== Agent 模式 =====
Mode: 0, // 0=全托管,1=半托管,默认 0
// ===== 半托管模式参数(Mode=1 时必需)=====
ListerIp: 'xx.xx.xx.xx', // Agent 服务器 IP
EndPoint: 'oss-cn-beijing-internal.aliyuncs.com', // 源端 Endpoint
// ===== 限速设置 =====
IsLimitSpeed: 0, // 0=不限速,1=限速,默认 0
LimitSpeed: 100, // 限速值(KB/s),IsLimitSpeed=1 时需要
LimitQPS: 1000, // QPS 限制
// ===== 预估信息 =====
EstimateDataSize: 1000, // 预估数据大小(GB)
EstimateFileCount: 100000, // 预估文件数量
// ===== 保存路径 =====
SaveType: 0, // 0=保存到根目录,1=保存到指定目录,默认 0
// SavePath: '/migrated/', // SaveType=1 时需要
// ===== 定时迁移 =====
IsCron: 0 // 0=否,1=是,默认 0
});
参数说明对照表
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| 基本信息 |
| JobName | string | ✅ | - | 任务名称,建议格式:{用途}-{日期} |
| 源端配置 |
| SrcBucket | string | ✅ | - | 源存储桶名称 |
| SrcSecretId | string | ✅ | - | 源端 SecretId/AccessKeyID |
| SrcSecretKey | string | ✅ | - | 源端 SecretKey/AccessKeySecret |
| SrcService | string | ❌ | OSS | 源服务类型:OSS/COS/AWS/Qiniu |
| 目标端配置 |
| DstBucket | string | ✅ | - | 目标存储桶名称(需包含 APPID) |
| DstSecretId | string | ✅ | - | 目标端 SecretId |
| DstSecretKey | string | ✅ | - | 目标端 SecretKey |
| DstService | string | ❌ | COS | 目标服务类型:COS |
| Header 迁移 |
| MigrationHeaderType | int | ❌ | 1 | 1=保留全部,2=丢弃全部,3=自定义替换 |
| MigrationHeader | array | ❌ | [] | Header 替换规则,MigrationHeaderType=3 时需要 |
| 文件过滤 |
| MigrationRuleType | int | ❌ | 1 | 1=不过滤,2=前缀匹配,3=正则匹配 |
| MigrationRule | array | ❌ | [] | 过滤规则,MigrationRuleType=2/3 时需要 |
| 时间过滤 |
| HasFileTime | int | ❌ | 0 | 0=不启用,1=启用时间过滤 |
| StartTime | string | 条件 | - | 开始时间,HasFileTime=1 时必需,格式:yyyy-MM-dd HH:mm:ss |
| EndTime | string | 条件 | - | 结束时间,HasFileTime=1 时必需,格式:yyyy-MM-dd HH:mm:ss |
| 文件冲突 |
| FileOverWrite | int | ❌ | 1 | 0=覆盖同名文件,1=跳过同名文件 |
| 存储类型 |
| StorageType | int | ❌ | 3 | 1=标准,2=低频,3=保持原属性,4=归档,5=智能分层,6=冷存储 |
| Agent 模式 |
| Mode | int | ❌ | 0 | 0=全托管,1=半托管 |
| ListerIp | string | 条件 | - | Agent IP,Mode=1 时必需 |
| EndPoint | string | 条件 | - | 源端 Endpoint,Mode=1 时必需 |
| 限速 |
| IsLimitSpeed | int | ❌ | 0 | 0=不限速,1=限速 |
| LimitSpeed | int | ❌ | 0 | 限速值(KB/s),IsLimitSpeed=1 时需要 |
| LimitQPS | int | ❌ | 0 | QPS 限制 |
| 预估信息 |
| EstimateDataSize | int | ❌ | 0 | 预估数据大小(GB) |
| EstimateFileCount | int | ❌ | 0 | 预估文件数量 |
| 保存路径 |
| SaveType | int | ❌ | 0 | 0=根目录,1=指定目录 |
| SavePath | string | 条件 | - | 保存路径,SaveType=1 时需要 |
| 定时迁移 |
| IsCron | int | ❌ | 0 | 0=否,1=是定时任务 |
❓ 常见问题
Q1: 迁移过程中源端数据变更怎么办?
当前版本创建的是一次性全量迁移任务。如需同步增量数据,需要重新创建迁移任务。同名文件处理策略基于MSP服务的默认配置。
Q2: 迁移失败如何处理?
- 查看任务状态和失败文件列表
- 失败原因会记录在任务结果中
- 可根据失败原因手动处理源文件后重新创建迁移任务
Q3: 凭证存储安全吗?
- 凭证以脱敏形式显示,避免完整暴露
- 建议用户妥善保管本地存储的凭证文件
- 日志中会避免记录完整的敏感信息
微信扫一扫