|
|
@@ -50,6 +50,19 @@ interface TaskBaiduUploadResult {
|
|
|
songId?: string;
|
|
|
uploadId?: string;
|
|
|
progress?: number;
|
|
|
+ currentPart?: number;
|
|
|
+ totalParts?: number;
|
|
|
+}
|
|
|
+
|
|
|
+// TaskPool进度消息接口
|
|
|
+interface BaiduUploadProgressMessage {
|
|
|
+ type: 'progress';
|
|
|
+ progress: number;
|
|
|
+ currentPart?: number;
|
|
|
+ totalParts?: number;
|
|
|
+ stage: 'md5' | 'upload' | 'create';
|
|
|
+ uploadedSize?: number;
|
|
|
+ totalSize?: number;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -81,7 +94,7 @@ async function executeBaiduUpload(params: TaskBaiduUploadParams): Promise<TaskBa
|
|
|
const PART_SIZE = 4 * 1024 * 1024; // 4MB分片大小
|
|
|
const totalParts = Math.ceil(fileSize / PART_SIZE);
|
|
|
|
|
|
- // 3. 计算分片MD5列表
|
|
|
+ // 3. 计算分片MD5列表(占总进度的10%)
|
|
|
const blockMd5List: string[] = [];
|
|
|
for (let i = 0; i < totalParts; i++) {
|
|
|
const start = i * PART_SIZE;
|
|
|
@@ -89,6 +102,19 @@ async function executeBaiduUpload(params: TaskBaiduUploadParams): Promise<TaskBa
|
|
|
const partData = fileData.slice(start, end);
|
|
|
const md5 = await simpleCalculateMD5(partData);
|
|
|
blockMd5List.push(md5);
|
|
|
+
|
|
|
+ // 发送MD5计算进度
|
|
|
+ const md5Progress = ((i + 1) / totalParts) * 10;
|
|
|
+ const progressMessage: BaiduUploadProgressMessage = {
|
|
|
+ type: 'progress',
|
|
|
+ progress: md5Progress,
|
|
|
+ currentPart: i + 1,
|
|
|
+ totalParts: totalParts,
|
|
|
+ stage: 'md5',
|
|
|
+ uploadedSize: Math.floor(fileSize * md5Progress / 100),
|
|
|
+ totalSize: fileSize
|
|
|
+ };
|
|
|
+ taskpool.Task.sendData(progressMessage);
|
|
|
}
|
|
|
|
|
|
// 4. 预上传(第一阶段)
|
|
|
@@ -110,14 +136,17 @@ async function executeBaiduUpload(params: TaskBaiduUploadParams): Promise<TaskBa
|
|
|
}
|
|
|
console.info(`heanup 预上传成功,uploadid: ${JSON.stringify(precreateResponse)}`);
|
|
|
const uploadServer = await simpleLocateUploadServer(accessToken, remotePath, precreateResponse.uploadid!);
|
|
|
- // 5. 分片上传
|
|
|
+ // 5. 分片上传(占总进度的80%)
|
|
|
const partsToUpload = precreateResponse.block_list || [];
|
|
|
Logger.info(`heanup 预上传返回block_list: ${JSON.stringify(partsToUpload)}, errno: ${precreateResponse.errno}`);
|
|
|
|
|
|
// 如果block_list为空,说明所有分片都已存在,直接跳过分片上传
|
|
|
-
|
|
|
Logger.info( `heanup 需要上传的分片列表: ${JSON.stringify(partsToUpload)}, 总计${partsToUpload.length}个分片`);
|
|
|
|
|
|
+ const baseProgress = 10; // MD5计算已完成
|
|
|
+ const uploadProgressRange = 80; // 上传进度范围
|
|
|
+ const uploadedParts = new Set<number>();
|
|
|
+
|
|
|
for (let i = 0; i < partsToUpload.length; i++) {
|
|
|
const partSeq = partsToUpload[i];
|
|
|
const start = partSeq * PART_SIZE;
|
|
|
@@ -127,10 +156,35 @@ async function executeBaiduUpload(params: TaskBaiduUploadParams): Promise<TaskBa
|
|
|
Logger.info( `heanup 开始上传分片${partSeq}, 大小: ${partData.byteLength}字节`);
|
|
|
await simpleUploadFilePart(uploadServer, accessToken, remotePath, precreateResponse.uploadid!, partSeq, partData);
|
|
|
Logger.info(`heanup 分片${partSeq}上传完成`);
|
|
|
+
|
|
|
+ // 记录已上传的分片并发送进度
|
|
|
+ uploadedParts.add(partSeq);
|
|
|
+ const uploadProgress = (uploadedParts.size / partsToUpload.length) * uploadProgressRange;
|
|
|
+ const totalProgress = baseProgress + uploadProgress;
|
|
|
+
|
|
|
+ const progressMessage: BaiduUploadProgressMessage = {
|
|
|
+ type: 'progress',
|
|
|
+ progress: totalProgress,
|
|
|
+ currentPart: uploadedParts.size,
|
|
|
+ totalParts: partsToUpload.length,
|
|
|
+ stage: 'upload',
|
|
|
+ uploadedSize: Math.floor(fileSize * totalProgress / 100),
|
|
|
+ totalSize: fileSize
|
|
|
+ };
|
|
|
+ taskpool.Task.sendData(progressMessage);
|
|
|
}
|
|
|
|
|
|
|
|
|
- // 6. 创建文件(第三阶段)
|
|
|
+ // 6. 创建文件(第三阶段,占总进度的10%)
|
|
|
+ const createFileProgressMessage: BaiduUploadProgressMessage = {
|
|
|
+ type: 'progress',
|
|
|
+ progress: 90,
|
|
|
+ stage: 'create',
|
|
|
+ uploadedSize: Math.floor(fileSize * 0.9),
|
|
|
+ totalSize: fileSize
|
|
|
+ };
|
|
|
+ taskpool.Task.sendData(createFileProgressMessage);
|
|
|
+
|
|
|
const createFileRequest: TaskCreateFileRequest = {
|
|
|
path: remotePath,
|
|
|
size: fileSize,
|
|
|
@@ -143,6 +197,16 @@ async function executeBaiduUpload(params: TaskBaiduUploadParams): Promise<TaskBa
|
|
|
throw new Error('创建文件失败:未获取到文件路径');
|
|
|
}
|
|
|
|
|
|
+ // 发送完成进度
|
|
|
+ const finalProgressMessage: BaiduUploadProgressMessage = {
|
|
|
+ type: 'progress',
|
|
|
+ progress: 100,
|
|
|
+ stage: 'create',
|
|
|
+ uploadedSize: fileSize,
|
|
|
+ totalSize: fileSize
|
|
|
+ };
|
|
|
+ taskpool.Task.sendData(finalProgressMessage);
|
|
|
+
|
|
|
return {
|
|
|
success: true,
|
|
|
filePath: filePath,
|
|
|
@@ -2815,23 +2879,30 @@ export class RemoteDriveManager {
|
|
|
Logger.info(TAG, `最终远程路径: ${remotePath}`);
|
|
|
Logger.info(TAG, '------------------------------');
|
|
|
|
|
|
- // 使用TaskPool执行上传任务
|
|
|
- const taskId = `baidu-upload-${song.id || Date.now()}`;
|
|
|
+ // 转换路径为百度网盘要求的格式
|
|
|
+ const baiduRemotePath = convertToBaiduPath(remotePath);
|
|
|
+ Logger.info(TAG, `原始路径: ${remotePath}, 转换后路径: ${baiduRemotePath}`);
|
|
|
+
|
|
|
+ // 使用TaskPool执行上传任务(支持进度消息)
|
|
|
Logger.info(TAG, '创建TaskPool上传任务...');
|
|
|
+ const taskParams: TaskBaiduUploadParams = {
|
|
|
+ filePath: song.filePath,
|
|
|
+ accessToken: accessToken,
|
|
|
+ remotePath: baiduRemotePath,
|
|
|
+ songName: song.name,
|
|
|
+ songId: song.id || `file-${Date.now()}`
|
|
|
+ };
|
|
|
|
|
|
- // 转换路径为百度网盘要求的格式
|
|
|
- const baiduRemotePath = convertToBaiduPath(remotePath);
|
|
|
- Logger.info(TAG, `原始路径: ${remotePath}, 转换后路径: ${baiduRemotePath}`);
|
|
|
+ const uploadTask: taskpool.Task = new taskpool.Task(executeBaiduUpload, taskParams);
|
|
|
|
|
|
- const taskParams: TaskBaiduUploadParams = {
|
|
|
- filePath: song.filePath,
|
|
|
- accessToken: accessToken,
|
|
|
- remotePath: baiduRemotePath,
|
|
|
- songName: song.name,
|
|
|
- songId: song.id || `file-${Date.now()}`
|
|
|
- };
|
|
|
-
|
|
|
- const uploadTask: taskpool.Task = new taskpool.Task(executeBaiduUpload, taskParams);
|
|
|
+ // 设置进度消息接收器
|
|
|
+ uploadTask.onReceiveData((progressData: BaiduUploadProgressMessage) => {
|
|
|
+ // 更新上传进度
|
|
|
+ this.uploadReceivedSize = progressData.uploadedSize || 0;
|
|
|
+ this.uploadTotalSize = progressData.totalSize || 0;
|
|
|
+ Logger.info(TAG, `百度网盘上传进度: ${progressData.progress.toFixed(1)}% (${progressData.currentPart || 0}/${progressData.totalParts || 0} ${progressData.stage})`);
|
|
|
+ this.notifyObservers(RemoteDriveManagerStates.UploadProgress);
|
|
|
+ });
|
|
|
|
|
|
// 提交任务到TaskPool
|
|
|
Logger.info(TAG, '提交上传任务到TaskPool...');
|
|
|
@@ -2849,9 +2920,8 @@ export class RemoteDriveManager {
|
|
|
|
|
|
Logger.info(TAG, '========== 百度网盘上传任务成功 ==========');
|
|
|
Logger.info(TAG, `文件名: ${song.name}`);
|
|
|
- Logger.info(TAG, `文件路径: ${result.filePath || song.filePath}`);
|
|
|
- Logger.info(TAG, `目标路径: ${result.remotePath || remotePath}`);
|
|
|
- Logger.info(TAG, `UploadId: ${result.uploadId || 'unknown'}`);
|
|
|
+ Logger.info(TAG, `文件路径: ${song.filePath}`);
|
|
|
+ Logger.info(TAG, `目标路径: ${remotePath}`);
|
|
|
Logger.info(TAG, `耗时: ${duration} 秒`);
|
|
|
Logger.info(TAG, '====================================');
|
|
|
|
|
|
@@ -2884,6 +2954,7 @@ export class RemoteDriveManager {
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 获取错误类型
|
|
|
* @param error 错误对象
|