/** * Uploader - 文件上传器 * 支持简单上传、分片上传、秒传检测、断点续传 * 浏览器环境适配版本 */ import { AxiosInstance } from 'axios'; import { Configuration } from '../configuration'; import { SMHError } from '../utils/ErrorHandler'; import { CommonLoader } from './CommonLoader'; import { TaskStatus, UploadCheckpoint, UploadOptions } from './types'; /** * Uploader类 - 文件上传器 * 支持秒传、简单上传、分块上传、断点续传 */ export declare class Uploader extends CommonLoader { private options; private upload_id?; private confirm_key?; private bucket?; private region?; private key?; private chunk_size; private part_info_list; private rapid_upload; private crc64?; private fileApi; private directoryApi; private autoCreateDirAttempted; private renewTimer?; private CHUNK_FILE_SIZE; private readonly MIN_SIZE_FOR_HASH; private readonly DEFAULT_PARALLEL; constructor(options: UploadOptions, configuration: Configuration, axiosInstance?: AxiosInstance); protected getTaskType(): string; /** * 检查任务是否被停止 */ private throwIfStopped; /** * 恢复checkpoint */ private restoreCheckpoint; /** * 获取checkpoint信息 */ getCheckpoint(): UploadCheckpoint; /** * 开始任务 */ start(): Promise; /** * 执行开始 */ private doStart; /** * 暂停任务 */ pause(): Promise; /** * 取消任务 */ cancel(): Promise; /** * 主运行流程 */ private run; /** * 执行上传流程 */ /** * 执行上传流程 * * 外层包装:当开启 autoCreateDir 且上传因目标父目录不存在(DirectoryNotFound) * 失败时,自动创建所需父目录后重试一次。 */ private executeUpload; /** * 派发上传:根据文件大小选择简单上传或分块上传 */ private dispatchUpload; /** * 判断错误是否为"目标父目录不存在"(DirectoryNotFound) * * 上传任务内部直接使用原始 axios 实例(未经过 SmhClient 的 SMHError 包装), * 因此这里从 AxiosError 中提取 serverCode 进行判断,避免依赖中文 message。 */ private isDirectoryNotFoundError; /** * 提取文件路径的父目录部分。 * - "a/b/c.txt" -> "a/b" * - "c.txt" -> ""(根目录下的文件,无父目录) */ private getParentDirPath; /** * 确保目录存在。 * * SMH 服务端的 createDirectory 会自动递归创建中间所需的各级父目录, * 因此这里只需对完整目录路径调用一次即可。 * * 使用默认的 ask 冲突策略(不可用 rename:rename 会把已存在的目录重命名为 * "bar (1)" 导致后续上传路径错位)。对"目录已存在"产生的 409 / * SameNameDirectoryOrFileExists 视为成功并吞掉——若父级实际是同名文件(真冲突), * 后续重试上传仍会报 DirectoryNotFound,届时由外层抛出原始错误。 */ private ensureDirectory; /** * 执行简单上传 */ private executeSimpleUpload; /** * 带重试的简单上传 */ private simpleUploadWithRetry; /** * 简单上传(使用 axios) */ private simpleUpload; /** * 执行分块上传 */ private executeMultipartUpload; /** * 上传单个分片 */ private uploadSinglePart; /** * 分块上传 */ private multipartUpload; /** * 动态计算分块大小 */ private calcAutoChunkSize; /** * 初始化分片信息 */ private initChunks; /** * 计算分块上传的 CRC64 */ private calculateMultipartCRC64; /** * 确认上传 */ private confirmUpload; /** * 续期上传任务 */ private renewUploadTask; /** * 安排续期定时器 */ private scheduleRenewal; /** * 清除续期定时器 */ private clearRenewalTimer; private getFileMetaFields; private toUploadData; private isNativeBlob; /** * 改变状态 */ protected changeState(state: TaskStatus, error?: SMHError): Promise; /** * 通知进度 */ protected notifyProgress(state: string, progress: number): void; /** * 通知分片完成 */ private notifyPartCompleted; /** * 处理错误 */ protected handleError(e: Error): Promise; }