鸿蒙应用开发:下载功能

简介: 鸿蒙应用开发:下载功能

鸿蒙系统不断发展,有与安卓、iOS 形成三足鼎立之势,且其在智能手机、智能穿戴、车载、家居等行业领域的应用越来越广泛。作为开发者,如何抓住鸿蒙生态崛起的机遇,解决开发挑战,创造更好的应用体验?欢迎您和我们一起探讨~

鸿蒙提供了多种API用于下载,今天我就拿request包来讲解下如何实现下载。

版本:

DevEco Studio 4.1 Release

SDK10

API
request API中介绍了两种下载方式:request.downloadFile和request.agent.create。如果仅限于下载,两者区别不大,仅仅是下载路径区别。前者的config可指定所有沙箱路径,后者的config只能指定缓存目录。但是若考虑到一些细节问题,如断点续传等,推荐第二种。

主代码
下载功能主代码要求输入下载地址(url)和下载文件名(name),并且首先基于文件名检查文件是否存在,然后创建下载任务,并且在下载过程中订阅了下载进度,即时将下载信息传递给页面进行渲染。

import fs from '@ohos.file.fs';
import request from '@ohos.request';
import Prompt from '@system.prompt';
import EventBus from './EventBus';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';

let downloadTask: request.agent.Task;
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;

export class DownLoader {

/**

  • 下载文件
  • @param url 文件地址
  • @param name 文件名
    */
    static async downloadthisFile(url,name) {
    let filePath = context.cacheDir+'/'+name;
    try {

    // 检查文件是否存在
    const fileExists = await checkFileExists(filePath);
    if (fileExists) {
    console.log("File already exists, deleting the existing file...");
    await fs.unlink(filePath); // 删除已存在的文件
    console.log("File deleted successfully.");
    }

    // 创建下载任务
    let config: request.agent.Config = {
    action: request.agent.Action.DOWNLOAD,
    url: url,
    saveas: './'+name,
    overwrite: true,
    mode: request.agent.Mode.FOREGROUND,
    index: 0,
    begins: 0,
    ends: -1,
    };

    try {
    downloadTask = await request.agent.create(getContext(), config);
    console.info(Succeeded in creating a download task. result: ${downloadTask.tid});
    downloadTask.start();
    Prompt.showToast({ message: "Download task started.", duration: 1000 });

    // 订阅下载进度
    if (downloadTask.tid) {

     let lastReceivedSize = 0;
     let lastTime = Date.now();
    
     // 监听下载进度
     let call = async (progress: request.agent.Progress) => {
       const Speed = calculateSpeed(progress.processed, lastTime, lastReceivedSize);
       const percent = (progress.processed / progress.sizes[0]) * 100;
       const size = (progress.sizes[0] / 1024 / 1024).toFixed(2); // MB
       console.log("进度 速度 大小", percent, Speed, size);
    
       // 直接更新状态
       EventBus.emit('downloadProgress', percent);
       EventBus.emit('downloadSpeed', Speed);
       EventBus.emit('downloadSize', size);
       console.log("Download task returned:", downloadTask.tid)
     };
    
     // 订阅下载进度
     downloadTask.on('progress', call);
    
     console.log("Download task returned:", downloadTask.tid);
    

    }
    } catch (err) {
    console.error(Failed to create a download task, Code: ${err.code}, message: ${err.message});
    }

    if (!downloadTask.tid)
    throw new Error("Download task failed, no task returned.");

    } catch (err) {
    console.error(Failed to download file. Error: ${err.message});
    }

    }

    /**

  • 暂停下载
    */
    static async pausedownload() {
    downloadTask.pause().then(() => {
    console.info(Succeeded in pausing a download task.);
    }).catch((err: BusinessError) => {
    console.error(Failed to pause the upload task, Code: ${err.code}, message: ${err.message});
    });
    }

    /**

  • 恢复下载
    */
    static async resumedownload() {
    downloadTask.resume().then(() => {
    console.info(Succeeded in resuming a download task.);
    }).catch((err: BusinessError) => {
    console.error(Failed to resume the download task, Code: ${err.code}, message: ${err.message});
    });
    }
    }

/**

  • 计算下载速度
  • @param receivedSize 已接收的字节数
  • @param lastTime 上次计算速度的时间戳
  • @param lastReceivedSize 上次计算速度时已接收的字节数
  • @returns 速度,单位KB/s
    */
    function calculateSpeed(receivedSize,lastTime,lastReceivedSize) {
    const currentTime = Date.now();
    const timeElapsed = (currentTime - lastTime) / 1000; // 转换为秒
    const bytesReceived = receivedSize - lastReceivedSize; // 新接收到的字节数

    // 计算速度
    const speed = timeElapsed > 0 ? (bytesReceived / timeElapsed) : 0; // 字节/秒

    // 更新历史数据
    lastTime = currentTime;
    lastReceivedSize = receivedSize;

    return Number((speed / 1024).toFixed(2)); // 转换为KB/s
    };

/**

  • 检查文件是否存在
  • @param filePath 文件路径
  • @returns Promise 文件是否存在
    */
    async function checkFileExists(filePath) {
    try {
    console.log("Checking file existence for:", filePath);
    await fs.stat(filePath);
    return true; // 文件存在
    } catch (err) {
    if (err.code === 'ENOENT') {
    return false; // 文件不存在
    } else {
    console.error(Error checking file existence: ${err.message});
    return false; // 处理其他错误
    }
    }
    }
    页面
    页面主体是两个输入框,输入下载地址(url)和下载文件名(name),执行下载的按钮、暂停(继续)按钮以及一个圆形进度条。

import { DownLoader } from '../common/Download';
import EventBus from '../common/EventBus';

@Entry
@Component
struct Index {
@State message: string = 'Hello World';
@State download: boolean = true;
@State url: string = '';
@State fileName: string = '';
@State percent: number = 0;

aboutToAppear(): void {
// 订阅下载进度更新
EventBus.on('downloadProgress', async (percent) => {
this.percent = percent;
console.log("Updated download progress:", this.percent);
});
}
build() {
Column() {
TextInput({ text: this.url, placeholder: 'input your download url' }).margin({ top: 20 })
.onSubmit((EnterKeyType) => {
console.info(EnterKeyType + '输入法回车键的类型值')
})
TextInput({ text: this.fileName, placeholder: 'input your download file name' }).margin({ top: 20 })
.onSubmit((EnterKeyType) => {
console.info(EnterKeyType + '输入法回车键的类型值')
})
Button('Download')
.width(150)
.margin({ top: 20 })
.onClick(async ()=>{
await DownLoader.downloadthisFile(this.url,this.fileName);
})
Button(this.download ? 'Pause' : 'Resume')
.width(150)
.margin({ top: 20 })
.onClick(async ()=>{
this.download = !this.download;
this.download ? DownLoader.resumedownload() : DownLoader.pausedownload();
})

  Progress({ value: this.percent, total: 100, type: ProgressType.ScaleRing }).width(100).height(100)
    .margin({top: 50})
    .visibility(this.percent >= 0 && this.percent <= 100 ? Visibility.Visible : Visibility.Hidden)
    .backgroundColor(Color.Black)
    .style({ strokeWidth: 15, scaleCount: 20, scaleWidth: 5 })    // 设置环形有刻度进度条宽度15,总刻度数为20,刻度宽度为5vp
}
.padding(20)
.width('100%')

}
}

下载过程

相关文章
|
8天前
|
移动开发 JavaScript 前端开发
HarmonyOS鸿蒙应用开发——探索原生与H5通信框架DSBridge
HarmonyOS版DSBridge是一个桥梁库,允许鸿蒙原生环境与JavaScript交互。它兼容Android和iOS的第三方DSBridge核心功能,支持同步和异步调用、命名空间API管理、进度回调及页面关闭监听等功能。主要特性包括适配鸿蒙NEXT版本、支持串行异步并发任务、兼容DSBridge 2.0与3.0版本JS脚本,并提供类形式集中管理API及自定义页面组件注册。源码仓库:HarmonyOS版 - DSBridge-HarmonyOS。安装命令为`ohpm install @hzw/ohos-dsbridge`。通过该库,开发者可以方便地在鸿蒙系统中实现原生与JS的高效交互。
71 1
|
9天前
|
编解码 API 数据安全/隐私保护
一个鸿蒙开发者的探索:实现相册访问功能
最近我决定开发一个鸿蒙App,旨在提供更好的照片管理体验。通过使用PhotoAccessHelper API,我实现了访问、显示和管理设备相册中的照片。过程中遇到了权限不足的问题,通过在config.json中添加权限声明并编写权限检查代码得以解决。此外,我还实现了分页加载和展示照片详细信息等功能,提升了用户体验。这次开发不仅让我掌握了API的使用,也深刻体会到鸿蒙系统对用户隐私和数据安全的重视。 总结这次开发,我不仅学到了技术知识,还明白了开发者保护用户数据安全的责任。未来将继续探索更多功能,欢迎关注和收藏!
103 70
|
2天前
|
API 开发者 UED
自学记录鸿蒙API 13:PreviewKit从文件预览到应用开发
通过学习API 13,我深入研究了**PreviewKit(文件预览服务)**。该模块支持快速预览多种文件类型(文本、图片、视频、音频、PDF等),为文件管理类应用提供系统级支持。本文分享了从搭建开发环境到实现单文件和多文件预览的全过程,并介绍了如何构建一个实用的文件预览助手应用。通过实践,不仅掌握了技术细节,还提升了个人开发能力。希望这些经验能为其他开发者带来启发与帮助。
33 10
自学记录鸿蒙API 13:PreviewKit从文件预览到应用开发
|
3天前
|
存储 API
鸿蒙元服务项目实战:终结篇之备忘录搜索功能实现
开发元服务,有很多的限制性因素,比如包的大小限制,相关API限制,所以,我们在实际开发的时候,具体Api能否使用,还需要去官网查看一下,目前,针对当前这个小项目,总结了几个小问题,大家在开发的过程中可以作为参考。
鸿蒙元服务项目实战:终结篇之备忘录搜索功能实现
|
10天前
|
JavaScript 容器
鸿蒙应用开发从入门到入行 - 篇6:数据监听器、滚动、侧滑功能
在本篇文章里,您将掌握监听器、滚动、侧滑等相关内容,助力你开发出更具交互的案例。
34 9
鸿蒙应用开发从入门到入行 - 篇6:数据监听器、滚动、侧滑功能
|
11天前
|
自然语言处理 搜索推荐 数据安全/隐私保护
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
鸿蒙登录页面设计展示了 HarmonyOS 5.0(Next)的未来美学理念,结合科技与艺术,为用户带来视觉盛宴。该页面使用 ArkTS 开发,支持个性化定制和无缝智能设备连接。代码解析涵盖了声明式 UI、状态管理、事件处理及路由导航等关键概念,帮助开发者快速上手 HarmonyOS 应用开发。通过这段代码,开发者可以了解如何构建交互式界面并实现跨设备协同工作,推动智能生态的发展。
98 10
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
|
10天前
|
Dart 索引
鸿蒙应用开发从入门到入行 - 篇8:Tabs选项卡页签视图切换
在本篇文章里,您将掌握使用Tabs选项卡做栏目分类,这是未来应用开发中极为常用的组件
38 7
鸿蒙应用开发从入门到入行 - 篇8:Tabs选项卡页签视图切换
|
10天前
|
JavaScript Java 容器
鸿蒙应用开发从入门到入行 - 篇4:层叠布局、自定义组件、ForEach
导读:在本篇文章里,您将掌握层叠布局、自定义组件的用法,特别是自定义组件将来的开发中必然会用,其中应该特别关注自定义组件的一些规范与装饰器。
44 7
鸿蒙应用开发从入门到入行 - 篇4:层叠布局、自定义组件、ForEach
|
10天前
|
人工智能 小程序 Android开发
鸿蒙应用开发从入门到入行 - 篇1:HarmonyOS介绍——带你深入理解鸿蒙特性
本文介绍了华为的HarmonyOS(鸿蒙系统),这是一个面向全场景的分布式操作系统,不仅适用于手机和平板,还支持电脑、车机、手表、电视等多种设备。文章详细解析了鸿蒙系统的三大特性:一次开发多端部署、可分可合自由流转、统一生态原生智能,并分析了鸿蒙系统为何能蚕食安卓市场份额的原因。猫林老师认为,鸿蒙凭借其先进的技术和国内政策支持,有望在未来的市场中占据重要地位。最后,文章提供了学习鸿蒙系统的建议和一些课后练习,帮助读者更好地理解和掌握这一系统。
71 7
鸿蒙应用开发从入门到入行 - 篇1:HarmonyOS介绍——带你深入理解鸿蒙特性
|
2天前
|
人工智能 数据可视化 API
自学记录鸿蒙API 13:Calendar Kit日历功能从学习到实践
本文介绍了使用HarmonyOS的Calendar Kit开发日程管理应用的过程。通过API 13版本,不仅实现了创建、查询、更新和删除日程等基础功能,还深入探索了权限请求、日历配置、事件添加及查询筛选等功能。实战项目中,开发了一个智能日程管理工具,具备可视化管理、模糊查询和智能提醒等特性。最终,作者总结了模块化开发的优势,并展望了未来加入语音助手和AI推荐功能的计划。
110 1

热门文章

最新文章