> 技术文档 > 鸿蒙next开发:文件上传下载(实现请求暂停、恢复与断点续传)_鸿蒙实现多任务下载、断点续传

鸿蒙next开发:文件上传下载(实现请求暂停、恢复与断点续传)_鸿蒙实现多任务下载、断点续传


往期鸿蒙全套实战文章必看:(附带鸿蒙全栈学习资料)

  • 鸿蒙开发核心知识点,看这篇文章就够了

  • 最新版!鸿蒙HarmonyOS Next应用开发实战学习路线

  • 鸿蒙HarmonyOS NEXT开发技术最全学习路线指南

  • 鸿蒙应用开发实战项目,看这一篇文章就够了(部分项目附源码)


实现请求暂停、恢复与断点续传

约束与限制

请求暂停、恢复与断点续传能力支持Phone,2in1,Tablet,Wearable设备。并且从5.1.1(19)开始,新增支持TV设备。

请求暂停、恢复

场景介绍

Remote Communication Kit提供了完善的功能,其中包括对请求的暂停和恢复的支持。这不仅包括接收暂停,也涵盖了发送暂停。

使用实例

  1. 导入需要的模块。
    import { rcp } from \'@kit.RemoteCommunicationKit\';import { util } from \'@kit.ArkTS\';
  2. 定义调试信息接口、调试信息源类型以及调试信息序列化函数,用于将调试信息序列化为StringifiedDebugInfo数组。函数首先根据infoSource的类型获取调试信息,然后使用TextDecoder将调试信息的data字段解码为字符串,并返回一个包含解码后的调试信息的数组。
    const HTTP_SERVER_POST: string = \"https://example.org/anything\";// 定义调试信息接口interface StringifiedDebugInfo { type: rcp.DebugEvent; data: string;};// 定义调试信息源类型type DebugInfoSource = undefined | rcp.DebugInfo[] | rcp.Response;// 定义调试信息序列化函数function debugInfoStringify(infoSource: DebugInfoSource): StringifiedDebugInfo[] { const debugInfo = Array.isArray(infoSource) ? (infoSource as rcp.DebugInfo[]) : (infoSource as rcp.Response).debugInfo; if (!debugInfo) { return []; } const decoder = util.TextDecoder.create(\'utf-8\'); return debugInfo.map((i: rcp.DebugInfo): StringifiedDebugInfo => { return { type: i.type, data: decoder.decodeToString(new Uint8Array(i.data)).trim(), }; });}
  3. 获取发送暂停和恢复事件,用于从调试信息中筛选出发送暂停和恢复事件。
    function getSendPausedEvents(debugInfo: DebugInfoSource) { return debugInfoStringify(debugInfo).filter((i) => i.data.startsWith(\'[[RCP]]: Pause sending\')); } function getSendResumedEvents(debugInfo: DebugInfoSource) { return debugInfoStringify(debugInfo).filter((i) => i.data.startsWith(\'[[RCP]]: Resume sending\')); }
  4. 编写发起请求的函数。
    const SendingPauseByTimeout = async (done: Function): Promise => { const session = rcp.createSession(); const request = new rcp.Request(HTTP_SERVER_POST); // 定义发送暂停策略,kind为\'timeout\',timeoutMs为1ms const sendPolicy: rcp.SendingPausePolicy = { kind: \'timeout\', timeoutMs: 1, }; // 定义暂停策略,sending字段引用了上述定义的发送暂停策略 const pausePolicy: rcp.PausePolicy = { sending: sendPolicy, }; // 设置请求的配置,包括传输策略和跟踪信息 request.configuration = { transfer: { pausePolicy: pausePolicy, }, tracing: { infoToCollect: { textual: true, }, }, }; // 定义请求体数据 const data = \'TestData\'; // 设置请求头,\'Content-Length\'字段表示请求体的长度 request.headers = { \'Content-Length\': data.length.toString(), }; // 初始化一个标志位,用于控制请求体的生成 let read = false; // 设置请求方法为POST request.method = \'POST\'; // 定义请求体内容生成函数,如果read为true,则返回空的ArrayBuffer,否则生成包含请求体数据的ArrayBuffer request.content = (maxSize) => { if (read) { return new ArrayBuffer(0); } read = true; const buffer = new ArrayBuffer(data.length); util.TextEncoder.create(\'utf-8\').encodeIntoUint8Array(data, new Uint8Array(buffer)); return buffer; }; // 发送请求并等待响应 const response = await session.fetch(request) // 从响应的调试信息中获取发送暂停和恢复事件 const pausedEvents = getSendPausedEvents(response); const resumedEvents = getSendResumedEvents(response); // 关闭会话 session.close(); // 调用完成回调函数 done();}

实现断点续传

场景介绍

在处理多任务并发或网络中断后需要接续上次任务的场景中,用户可以通过定义TransferRange对象的from和to属性来控制数据的截取范围。下载的内容可以被准确地截取并拼接到目标文件中,确保数据的完整性和一致性,提高了任务的可靠性,开发者可以灵活地管理和恢复下载过程。

使用示例

  1. 导入模块。
    import { rcp } from \'@kit.RemoteCommunicationKit\';import { BusinessError } from \'@kit.BasicServicesKit\';
  2. 创建session,定义请求url及对request进行配置。
    // 创建会话const session = rcp.createSession();// 定义服务器地址const kHttpServerAddress = \"http://www.example.com/fetch\";// 创建请求const request = new rcp.Request(kHttpServerAddress, \"GET\");
  3. 定义HTTP请求函数。
    function httpRequest() { // 假设我们有一个存储上次传输位置的变量 let lastTransferPosition = 100; // 上次传输的位置 // 设置请求的范围,基于上次传输位置 request.transferRange = { from: lastTransferPosition, to: lastTransferPosition + 100 }; // 发起请求 session.fetch(request).then((rep: rcp.Response) => { if (rep.body) { // 处理响应 console.info(`Response succeeded: ${rep}`); // 检查是否需要继续传输,如果Content-Range字段存在,说明文件还未传输完成,需要继续传输 if (rep.headers[\'Content-Range\']) { // 更新上次传输位置 lastTransferPosition += rep.body?.byteLength; // 递归调用,继续传输 continueTransfer(lastTransferPosition); } else { console.info(\"文件传输完成\"); } } else { return; } }).catch((err: BusinessError) => { console.error(`Response err: Code is ${err.code}, message is ${JSON.stringify(err)}`); });}
  4. 定义递归调用函数。
    // 递归调用函数,用于继续传输function continueTransfer(position: number) { request.transferRange = { from: position, to: position + 100 }; session.fetch(request).then((rep) => { if (rep.body) { // 处理响应 console.info(`Response succeeded: ${rep}`); // 更新上次传输位置 position += rep.body.byteLength; // 再次调用继续传输 continueTransfer(position); } else { return; } }).catch((err: BusinessError) => { console.error(`Continue transfer error: Code is ${err.code}, message is ${err.message}`); });}