HarmonyOS 下载断点续传不能取消,失败没有错误原因?

下载断点续传接口文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-request-V5\#offfailed10

目前遇到的问题:

1、下载断点续传在下载过程中,app终止时下载任务还在执行中,第二次打开发现下载文件已经成功了。

2、下载失败没有错误信息,无法定位错误来源。例如下载begin越界导致的失败。

代码如下:

import { Response } from '../DownloadResponse';
import { Chain, Interceptor, Task } from './Interceptor';
import { request } from '@kit.BasicServicesKit';
import { logger } from '../utils/Logger';
import { Directory, File } from '../context/FileManager';
import { exist, getFileSize } from '../utils/fileUtils';

const TAG: string = 'DownloadInterceptor';

export class DownloadInterceptor implements Interceptor {
  async intercept(chain: Chain): Promise<Response> {
    const fileManager = chain.request().context.fileManager;
    const downloadRequest = chain.request();
    const task = chain.task();
    const targetPath = fileManager.getFilePath(downloadRequest.id, Directory.TMP, File.DOWNLOAD)
    let size = 0
    if (await exist(targetPath)) {
      size = await getFileSize(targetPath)
    }
    const downloadConfig: request.agent.Config = {
      action: request.agent.Action.DOWNLOAD,
      url: downloadRequest.entity.url || '',
      method: 'GET',
      title: 'download',
      mode: request.agent.Mode.BACKGROUND,
      begins: size > 0 ? size : 0,
      retry: true,
      network: request.agent.Network.ANY,
      saveas: targetPath,
      overwrite: true,
    };
    logger.info(`downloadFile, downloadConfig = ${JSON.stringify(downloadConfig)}`);

    try {
      const downloadTask = await request.agent.create(chain.request().context.context, downloadConfig);

      const downloadPromise = new Promise<Response>((resolve) => {

        const cancel = () => {
          this.deleteTask(downloadTask);
          this.unregister(task, cancel)
          resolve(Response.fail("downloadTask cancel"));
        };
        this.register(task, cancel)

        downloadTask.on('progress', (progress: request.agent.Progress) => {
          logger.info(TAG, `progress, progress = ${progress.processed} ${progress.state} ${JSON.stringify(progress)}`);
          const currentSize = progress.processed + size;
          const totalSize = progress.sizes[0] + size;
          let progressNum: number = Math.floor(currentSize / totalSize * 100);
          if (progressNum <= 100) {
            chain.request().onProgress(currentSize, totalSize, progressNum, -1)
          }
        });

        downloadTask.on('completed', (progress: request.agent.Progress) => {
          logger.info(TAG, `completed, completed = ${JSON.stringify(progress)}`);
          this.deleteTask(downloadTask);
          this.unregister(task, cancel)
          const totalSize = progress.sizes[0] + size;
          chain.request().onProgress(totalSize, totalSize, 100, -1)
          const response = Response.success(targetPath, Response.SOURCE_NETWORK)
          response.extra['downloadSize'] = progress.sizes[0]
          resolve(response);
        });

        downloadTask.on('failed', async (progress: request.agent.Progress) => {
          logger.info(TAG, `failed, completed = ${JSON.stringify(progress)}`);
          this.deleteTask(downloadTask);
          this.unregister(task, cancel)
          resolve(Response.fail("downloadTask fail"));
        });
      });
      await downloadTask.start();
      return downloadPromise;
    } catch (err) {
      logger.error(TAG, `downloadTask err, err = ${JSON.stringify(err)}`);
      return Response.fail('downloadTask err', err)
    }
  }

  register(task: Task, cancel: () => void) {
    task.on('cancel', cancel);
  }

  unregister(task: Task, cancel: () => void) {
    task.off('cancel', cancel);
  }

  async deleteTask(downloadTask: request.agent.Task) {
    try {
      downloadTask.off('progress');
      downloadTask.off('completed');
      downloadTask.off('failed');
      await request.agent.remove(downloadTask.tid);
    } catch (err) {
      logger.info(TAG, `deleteTask fail, err= ${JSON.stringify(err)}`);
    }
  }
}

export const DefaultDownload = new DownloadInterceptor();
阅读 502
1 个回答

断点续传的文档和示例参考:

https://gitee.com/harmonyos\_samples/remote-communication-kit\_-sample-code\_-arkts/blob/master/entry/src/main/ets/pages/transferRange.ets

https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/remote-communication-rcp-V5\#section838945575618

断点续传的实现需要依赖于服务器,客户端仅支持通过设置下载的开始位置和结束位置来控制是否断点续传begins和ends当前能实现基础的分段上传下载能力,完整的断点续传功能需要自行实现具体的下载拼接逻辑。overwrite若设置为false则在第二次下载时会报错文件已存在,若设置为true则会覆写此文件。具体实现逻辑可参考设置overwrite为true,下载中断后需要一个逻辑重命名并将两次下载文件进行拼接,下载完成并拼接后覆盖之前的下载文件。

let config: request.agent.Config = {
  action: request.agent.Action.DOWNLOAD,
  url: '资源链接',
  title: 'taskOnTest',
  description: 'Sample code for event listening',
  mode: request.agent.Mode.FOREGROUND,
  overwrite: false,
  method: "GET",
  data: '',
  saveas: "./",
  network: request.agent.Network.WIFI,
  metered: false,
  roaming: true,
  retry: true,
  redirect: true,
  index: 0,
  begins: 0,
  ends: -1,
  gauge: false,
  precise: false,
  token: "it is a secret"
};
request.agent.create(getContext(), config).then((task: request.agent.Task) => {
  task.on('progress', (progress: request.agent.Progress) => {
    console.info('upload task progress:' + progress);
  });
  task.on('completed', (progress: request.agent.Progress) => {
    console.info('upload task completed:' + progress);
  });
  task.on('failed', (progress: request.agent.Progress) => {
    console.info('upload task failed:' + progress);
  });
  task.start(() => {
    console.info('start task success');
  })
  console.info(Succeeded in creating a upload task. result: ${task.tid});
}).catch((err: BusinessError) => {
  console.error(Failed to create a upload task, Code: ${err.code}, message: ${err.message});
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进