前期准备
开始操作前,确保您已经完成了 SDK 初始化。如果您还没有初始化 SDK,请先参考快速入门文档完成。
上传文件
本文介绍如何通过 SMH JS SDK 进行文件上传,包括简单上传、分片上传、秒传检测、断点续传、暂停/恢复、取消上传等功能。
功能特性
简单上传 - 适用于小文件的直接上传
分片上传 - 大文件自动分片并发上传,提升上传速度
秒传功能 - 文件 hash 匹配时直接完成上传,无需重新上传
断点续传 - 支持暂停后从断点继续上传,节省流量和时间
暂停/恢复 - 随时暂停和恢复上传任务
取消上传 - 取消上传并清理服务端临时资源
进度监控 - 实时监控上传进度、速度和剩余时间
事件监听 - 丰富的事件系统,监听上传过程中的各种状态变化
快速开始
async function uploadFile(browserFile) {try {// 创建上传任务(同步方法,无需 await)const task = smh.createUploadTask({filePath: `/uploads/${browserFile.name}`, // 远端保存路径file: browserFile, // 浏览器 File 对象});// 监听上传进度task.on('progress', (data) => {console.log(`上传进度: ${data.progress.toFixed(2)}%`);console.log(`已上传: ${data.loaded} / ${data.total} 字节`);console.log(`速度: ${data.speed} 字节/秒`);console.log(`剩余时间: ${data.leftTime} 秒`);});// 监听状态变化task.on('statechange', (data) => {console.log(`状态变化: ${data.state}`);});// 开始上传(异步方法,需要 await)await task.start();console.log('上传文件成功!');} catch (error) {console.error('上传失败:', error.message);}}// 配合 <input type="file"> 使用const input = document.querySelector('input[type="file"]');input.addEventListener('change', () => {const file = input.files[0];if (file) {uploadFile(file);}});
参数说明
参数名 | 参数描述 | 类型 | 是否必填 | 默认值 |
filePath | 远端文件保存路径 | String | 是 | - |
file | 浏览器 File 对象(通过 <input type="file"> 或拖拽等方式获取) | File | 是 | - |
spaceId | 空间 ID(SMHClient 已设置时可省略) | String | 否 | - |
userId | 用户 ID | String | 否 | - |
chunkSize | 分片大小(MB),分片上传时每个分片的大小 | Number | 否 | 5 |
parallel | 并发上传数(分片上传时同时上传的分片数) | Number | 否 | 2 |
partFileSize | 触发分片上传的文件大小阈值(MB),超过此大小自动使用分片上传 | Number | 否 | 32 |
conflictResolutionStrategy | 文件冲突解决策略,可选值:ask、overwrite、rename | String | 否 | rename |
enableInstantUpload | 是否启用秒传功能,当文件已存在时直接完成上传 | Boolean | 否 | true |
trafficLimit | 单链接上传限速,范围 100KB/s - 100MB/s,单位:字节/秒(B/s) | Number | 否 | - |
checkpoint | 断点信息(用于恢复上传) | Object | 否 | - |
autoCreateDir | 目标目录不存在时是否自动创建(服务端递归创建父目录)后重试上传 | Boolean | 否 | false |
labels | 文件简易标签列表 | Array<String> | 否 | - |
category | 文件自定义分类 | String | 否 | - |
onProgress | 进度回调函数 | Function | 否 | - |
onStateChange | 状态变化回调函数 | Function | 否 | - |
onPartComplete | 分片完成回调函数 | Function | 否 | - |
verbose | 是否输出详细日志,调试时使用 | Boolean | 否 | false |
上传模式
1. 简单上传
适用于小文件(小于
partFileSize,默认 32MB)。SDK 自动判断文件大小选择上传模式。const task = smh.createUploadTask({filePath: '/uploads/small-file.txt',file: browserFile,});await task.start();
2. 分片上传
适用于大文件(大于
partFileSize),自动分片并发上传。分片上传支持签名自动续期,长时间上传不会因签名过期而失败。const task = smh.createUploadTask({filePath: '/uploads/large-video.mp4',file: browserFile,chunkSize: 5, // 每个分片 5MBparallel: 2, // 同时上传 2 个分片partFileSize: 32, // 超过 32MB 使用分片上传});// 监听分片完成事件task.on('partialcomplete', (data) => {console.log(`分片 ${data.partInfo.part_number} 上传完成`);});await task.start();
事件监听
上传任务支持多种事件监听,方便实时监控上传状态。
1. progress 事件
监听上传进度变化。
task.on('progress', (data) => {console.log(`进度: ${data.progress.toFixed(2)}%`);console.log(`已上传: ${data.loaded} 字节`);console.log(`总大小: ${data.total} 字节`);console.log(`当前速度: ${data.speed} 字节/秒`);console.log(`剩余时间: ${data.leftTime} 秒`);});
事件数据
字段 | 类型 | 说明 |
progress | Number | 上传进度(0-100) |
loaded | Number | 已上传字节数 |
total | Number | 文件总字节数 |
speed | Number | 当前上传速度(字节/秒) |
leftTime | Number | 预计剩余时间(秒) |
2. statechange 事件
监听任务状态变化。
task.on('statechange', (data) => {console.log(`状态变化: ${data.state}`);if (data.state === 'success') {console.log('上传成功!');} else if (data.state === 'rapid_success') {console.log('秒传成功!');} else if (data.state === 'error') {console.error('上传失败:', data.error);}});
任务状态
状态 | 说明 |
waiting | 等待开始 |
start | 开始处理 |
computing_hash | 计算哈希中(用于秒传检测和 CRC64 校验) |
created | 已创建上传任务 |
running | 正在上传 |
paused | 已暂停 |
confirming | 确认中(上传完成后与服务端确认) |
success | 上传成功 |
rapid_success | 秒传成功 |
error | 上传失败 |
canceled | 已取消 |
3. partialcomplete 事件
监听分片上传完成(仅分片上传模式)。
task.on('partialcomplete', (data) => {console.log(`分片 ${data.partInfo.part_number} 完成`);console.log(`分片大小: ${data.partInfo.chunk_size} 字节`);console.log(`分片范围: ${data.partInfo.from}-${data.partInfo.to}`);});
秒传功能
秒传功能可以大幅提升上传效率,当后端检测到文件已存在时,直接返回成功,无需重新上传。
SDK 会自动计算文件的 beginningHash(文件头部哈希),服务端匹配后可能需要进一步计算 fullHash(完整文件哈希)来确认。文件大小需 ≥ 1MB 才会触发秒传检测。
const task = smh.createUploadTask({filePath: '/uploads/existing-file.txt',file: browserFile,enableInstantUpload: true, // 默认即为 true});// 监听秒传事件task.on('statechange', (data) => {if (data.state === 'rapid_success') {console.log('秒传成功!文件已存在,无需上传。');} else if (data.state === 'success') {console.log('上传成功!文件已上传完成。');}});await task.start();
暂停和恢复
暂停上传
const task = smh.createUploadTask({filePath: '/uploads/large-video.mp4',file: browserFile,});// 监听进度,在 30% 时暂停task.on('progress', (data) => {if (data.progress >= 30 && task.state === 'running') {console.log('暂停上传...');task.pause();}});task.on('statechange', (data) => {if (data.state === 'paused') {console.log('上传已暂停');// 保存断点信息const checkpoint = task.getCheckpoint();console.log(`暂停进度: ${checkpoint.progress.toFixed(2)}%`);}});await task.start();
恢复上传(断点续传)
使用保存的 checkpoint 信息恢复上传:
// 方式一:直接恢复已暂停的任务await task.start();// 方式二:使用 checkpoint 创建新任务恢复上传const checkpoint = task.getCheckpoint();const newTask = smh.createUploadTask({filePath: '/uploads/large-video.mp4',file: browserFile, // 需要同一个 File 对象checkpoint: checkpoint,});await newTask.start();
注意:
断点续传要求使用相同的
File 对象。如果页面刷新后 File 对象丢失,需要用户重新选择文件。取消上传
取消上传会通知服务端清理临时资源(如未确认的分片),并重置任务状态。
const task = smh.createUploadTask({filePath: '/uploads/large-video.mp4',file: browserFile,});// 监听进度,在 20% 时取消let wasCanceled = false;task.on('progress', (data) => {if (!wasCanceled && data.progress >= 20) {wasCanceled = true;console.log('取消上传...');task.cancel();}});task.on('statechange', (data) => {if (data.state === 'canceled') {console.log('上传已取消');}});await task.start();
下载文件
本文介绍如何进行文件下载,包括浏览器 URL 下载、流式下载、分片下载、断点续传、暂停/恢复、取消下载等功能。
功能特性
URL 下载 - 浏览器原生下载,零内存占用,适合任意大小文件
流式下载 - 使用
fetch + ReadableStream,实时获取下载数据分片下载 - 大文件自动分片并发下载,提升下载速度
CRC64 校验 - 下载完成后自动校验数据完整性
断点续传 - 支持暂停后从断点继续下载
暂停/恢复 - 随时暂停和恢复下载任务
取消下载 - 取消下载并释放内存
进度监控 - 实时监控下载进度、速度和剩余时间
事件监听 - 丰富的事件系统,监听下载过程中的各种状态变化
快速开始
JS SDK 提供两种下载方式:
方式一:URL 下载(推荐)
通过
<a> 标签触发浏览器原生下载,不会将文件内容加载到内存中,适合任意大小的文件下载。// 基础用法await smh.downloadByUrl({filePath: '/documents/example.pdf',});// 自定义保存文件名await smh.downloadByUrl({filePath: '/documents/example.pdf',fileName: '我的文档.pdf',});
参数说明:
参数名 | 参数描述 | 类型 | 是否必填 | 默认值 |
filePath | 远端文件路径 | String | 是 | - |
spaceId | 空间 ID(SMHClient 已设置时可省略) | String | 否 | - |
userId | 用户 ID | String | 否 | - |
trafficLimit | 单链接下载限速,单位:字节/秒(B/s) | Number | 否 | - |
historyId | 历史版本 ID,下载指定历史版本时传入,不传默认为最新版 | String | 否 | - |
internalDomain | 是否使用内网域名,0 或 1,适用于同地域内网访问场景以提升访问速度 | Number | 否 | 0 |
fileName | 下载保存的文件名,默认从 filePath 提取 | String | 否 | - |
工作原理:
1. 调用文件信息接口获取 COS 签名下载 URL(cosUrl)
2. 创建一个隐藏的
<a> 标签,设置 href 为下载 URL,download 为文件名3. 模拟点击触发浏览器原生下载
4. 下载过程由浏览器接管,不占用 JS 内存
说明:
URL 下载不支持进度监控、暂停/恢复等功能。如果需要这些能力,请使用流式下载。
方式二:流式下载
使用
fetch + ReadableStream 将文件下载到内存中,返回 Blob 对象。适合需要在前端处理文件内容的场景(如预览、二次处理等)。async function downloadFile() {try {// 创建下载任务(同步方法,无需 await)const task = smh.createDownloadTask({filePath: '/documents/example.pdf',});// 监听下载进度task.on('progress', (data) => {console.log(`下载进度: ${data.progress.toFixed(2)}%`);console.log(`已下载: ${data.loaded} / ${data.total} 字节`);});// 监听状态变化task.on('statechange', (data) => {console.log(`状态变化: ${data.state}`);});// 开始下载await task.start();// 获取下载结果const blob = task.getResult();console.log('文件下载成功!', blob);} catch (error) {console.error('下载失败:', error.message);}}
使用 startAndGetBlob 直接获取 Blob
startAndGetBlob() 方法在下载完成后直接返回 Blob 对象,使用更加便捷:async function downloadAndPreview() {const task = smh.createDownloadTask({filePath: '/images/photo.jpg',});// 直接获取 Blobconst blob = await task.startAndGetBlob();// 创建预览 URLconst url = URL.createObjectURL(blob);const img = document.createElement('img');img.src = url;document.body.appendChild(img);}
参数说明
参数名 | 参数描述 | 类型 | 是否必填 | 默认值 |
filePath | 远端文件路径 | String | 是 | - |
spaceId | 空间 ID(SMHClient 已设置时可省略) | String | 否 | - |
userId | 用户 ID | String | 否 | - |
chunkSize | 分片大小(MB) | Number | 否 | 5 |
parallel | 并发下载数(分片下载时) | Number | 否 | 2 |
partFileSize | 触发分片下载的文件大小阈值(MB) | Number | 否 | 32 |
trafficLimit | 单链接下载限速,单位:字节/秒(B/s) | Number | 否 | - |
checkpoint | 断点信息(用于恢复下载) | Object | 否 | - |
onProgress | 进度回调函数 | Function | 否 | - |
onStateChange | 状态变化回调函数 | Function | 否 | - |
onPartComplete | 分片完成回调函数 | Function | 否 | - |
verbose | 是否输出详细日志,调试时使用 | Boolean | 否 | false |
下载模式
1. 简单下载
适用于小文件(小于
partFileSize,默认 32MB),使用单个 fetch 请求完成下载。const task = smh.createDownloadTask({filePath: '/downloads/small-file.txt',});const blob = await task.startAndGetBlob();
2. 分片下载
适用于大文件(大于
partFileSize),自动分片并发下载。每个分片使用 HTTP Range 请求下载,下载完成后自动合并为完整的 Blob。const task = smh.createDownloadTask({filePath: '/downloads/large-video.mp4',chunkSize: 5, // 每个分片 5MBparallel: 2, // 同时下载 2 个分片partFileSize: 32, // 超过 32MB 使用分片下载});// 监听分片完成事件task.on('partialcomplete', (data) => {console.log(`分片 ${data.partInfo.part_number} 下载完成`);});const blob = await task.startAndGetBlob();
事件监听
下载任务支持多种事件监听,方便实时监控下载状态。
1. progress 事件
监听下载进度变化。
task.on('progress', (data) => {console.log(`进度: ${data.progress.toFixed(2)}%`);console.log(`已下载: ${data.loaded} 字节`);console.log(`总大小: ${data.total} 字节`);console.log(`当前速度: ${data.speed} 字节/秒`);console.log(`剩余时间: ${data.leftTime} 秒`);});
事件数据:
字段 | 类型 | 说明 |
progress | Number | 下载进度(0-100) |
loaded | Number | 已下载字节数 |
total | Number | 文件总字节数 |
speed | Number | 当前下载速度(字节/秒) |
leftTime | Number | 预计剩余时间(秒) |
2. statechange 事件
监听任务状态变化。
task.on('statechange', (data) => {console.log(`状态变化: ${data.state}`);if (data.state === 'success') {console.log('下载成功!');} else if (data.state === 'error') {console.error('下载失败:', data.error);}});
任务状态:
状态 | 说明 |
waiting | 等待开始 |
start | 开始下载 |
preparing | 准备中(获取下载 URL、初始化分片) |
running | 下载中 |
paused | 已暂停 |
success | 下载成功 |
error | 下载失败 |
canceled | 已取消 |
3. partialcomplete 事件
监听分片下载完成(仅分片下载模式)。
task.on('partialcomplete', (data) => {console.log(`分片 ${data.partInfo.part_number} 完成`);console.log(`分片大小: ${data.partInfo.size} 字节`);console.log(`分片范围: ${data.partInfo.start}-${data.partInfo.end}`);});
暂停和恢复
暂停下载
const task = smh.createDownloadTask({filePath: '/videos/large-video.mp4',});// 监听进度,在 30% 时暂停task.on('progress', (data) => {if (data.progress >= 30 && task.state === 'running') {console.log('暂停下载...');task.pause();}});task.on('statechange', (data) => {if (data.state === 'paused') {console.log('下载已暂停');// 保存断点信息const checkpoint = task.getCheckpoint();console.log(`暂停进度: ${checkpoint.progress.toFixed(2)}%`);}});await task.start();
恢复下载
// 方式一:直接恢复已暂停的任务await task.start();// 方式二:使用 checkpoint 创建新任务恢复const checkpoint = task.getCheckpoint();const newTask = smh.createDownloadTask({filePath: '/videos/large-video.mp4',checkpoint: checkpoint,});await newTask.start();
注意:
简单下载(非分片)暂停后恢复时会从头重新下载。分片下载支持真正的断点续传,已完成的分片不会重复下载。
取消下载
取消下载会清理所有已下载的分片数据并释放内存。
const task = smh.createDownloadTask({filePath: '/videos/large-video.mp4',});// 监听进度,在 20% 时取消let wasCanceled = false;task.on('progress', (data) => {if (!wasCanceled && data.progress >= 20) {wasCanceled = true;console.log('取消下载...');task.cancel();}});task.on('statechange', (data) => {if (data.state === 'canceled') {console.log('下载已取消');}});await task.start();