当前位置: 首页 > news >正文

HarmonyOS优化应用文件上传下载慢问题性能优化二

常见场景和解决方案
场景1:低带宽网络上传琐碎文件场景
在网络连接较差,低带宽的网络环境中,HTTP连接的建立耗时可能会大幅提升。这时候进行数据压缩可以加快页面加载速度,并减少HTTP请求数量和移动数据流量。
场景2:处理大量资源的场景
如应用商店、网盘应用等,这类应用通常拥有大体积的文件资源。当用户从暂停或者断网中重新恢复时,如果从头开始上传下载则会额外耗费大量的时间。此时可以采用断点续传方法进行上传下载。
(一)数据压缩
数据压缩是指在应用中对数据进行压缩,以减少存储空间和数据传输量、节省带宽,提高加载速度。数据压缩通常在网络传输和存储方面发挥着重要作用,特别是在处理大量数据或需要频繁传输数据的场景下。
在应用开发中,常见的数据压缩技术分类如下:
有损压缩:仅限图片视频音频等文件适用。通过减少图片视频文件的分辨率,降低音频的音质等手段,以减少文件的大小,来实现减少加载时间和带宽消耗。
无损压缩:对一些零碎文件可以使用 zlib(Zip模块)来进行打包压缩,减少上传请求次数;对一些大文件可以利用缓存技术,服务器将曾经上传过的大文件MD5码缓存起来,本地在上传前预生成MD5码并传输到服务器进行比对,如果相同则说明服务器存在该文件,可以跳过该文件上传,从而省略重复传输时间。
以批量上传照片(分辨率为480*640,24位,平均大小50~120KB)为例,在设备上测试的结果如下表所示:
 

HarmonyOS优化应用文件上传下载慢问题性能优化二-鸿蒙开发者社区


图2 上传数量和耗时对比图表
 

HarmonyOS优化应用文件上传下载慢问题性能优化二-鸿蒙开发者社区


由于上传耗时受到网络状态影响,偏差较大,结果取的几次测量结果的最小值。但是仍然可以从数据中看出,优化前的耗时基本为线性增长,压缩优化后的耗时在上传文件数量较低时并不明显,还会因为多余的压缩处理影响耗时。不过随着上传的照片数量增多,优化后的耗时和优化之前的耗时差距越来越明显,优化效果越好。
数据压缩的相关示例代码如下:
导入相关模块:

import { common } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit'
import { zlib } from '@kit.BasicServicesKit';

    创建压缩上传相关类:

    class ZipUpload {// 创建任务前存放的uriprivate waitList: Array<string> = [];// 需要上传的文件uriprivate fileUris: Array<string> = [];...
    }

      建立用于接收图库图片的临时文件夹,并将整个临时文件夹打包添加到待上传list内:

      // 文件压缩处理
      async zipUploadFiles(fileUris: Array<string>): Promise<void> {this.context = getContext(this) as common.UIAbilityContext;let cacheDir = this.context.cacheDir;let tempDir = fileIo.mkdtempSync(`${cacheDir}/XXXXXX`);// 将图库图片获取的uri放入fileUris中,遍历复制到临时文件夹for (let i = 0; i < fileUris.length; i++) {let fileName = fileUris[i].split('/').pop();let resourceFile: fileIo.File = fileIo.openSync(fileUris[i], fileIo.OpenMode.READ_ONLY);fileIo.copyFileSync(resourceFile.fd, `${tempDir}/${fileName}`, 0);fileIo.closeSync(resourceFile);}// 文件压缩,将之前生成的临时文件夹内打包到test.zip内let options: zlib.Options = {level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION,memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT,strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY};let data = await zlib.compressFile(tempDir, `${cacheDir}/test.zip`, options);// 删除临时文件夹fileIo.rmdirSync(tempDir);// 将生成的zip包放到传输队列this.waitList.push(`${cacheDir}/test.zip`);
      }

        (二)断点续传
        断点续传功能的实现,不管是应用端还是服务器端都需要用到合理的技术来互相协同。在实际开发中,开发者无需亲自实现断点续传功能,只需对SDK进行合理配置。
        在应用端需要用到的技术和API:
        fileIo(文件管理):用于处理文件上传操作,提供了读取文件内容,文件分片和组合的功能。
        hash(文件哈希处理):用于实现文件MD5的计算,将计算的MD5值预先传到服务器端进行预处理,实现文件秒传,同时确保传输的准确性和可靠性。
        request(上传下载):用于实现文件上传操作,并支持在上传过程中的断点续传功能。
        在服务器端需要用到的技术:
        协议需要支持Range:用于在服务器端支持范围请求,方便处理文件上传下载断点续传功能。
        文件校验相关逻辑:需要实现校验文件是否有错,确保在传输中断后能够准确恢复并继续传输。
        通过结合应用端和服务器端的相关技术,可以共同实现高效且可靠的文件断点续传功能,提供更好的用户体验并确保数据传输的稳定性。
        本文基于上传和下载中的后台上传场景,给出了部分断点续传的示例代码,具体可以参考该工程。
        (三)文件上传
        对于大文件断点续传上传,本文采用request(上传下载)模块中的request.agent任务托管接口,可以自动实现暂停继续重试等操作,无需手动将文件分片和记录上传分片信息。流程图如下图所示:
        图3 断点续传上传流程图
         

        HarmonyOS优化应用文件上传下载慢问题性能优化二-鸿蒙开发者社区


        导入相关模块:

        import { common } from '@kit.AbilityKit';
        import { request } from '@kit.BasicServicesKit';

          创建相关上传类:

           class Upload {// 后台任务private backgroundTask: request.agent.Task | undefined = undefined;// 创建任务前存放的uriprivate waitList: Array<string> = [];...
          }

            配置Config,创建后台上传任务:

            private config: request.agent.Config = {action: request.agent.Action.UPLOAD,headers: HEADER,url: '',mode: request.agent.Mode.BACKGROUND,method: 'POST',title: 'upload',network: request.agent.Network.ANY,data: [],token: 'UPLOAD_TOKEN'
            }
            ...
            // 转换uri
            private async getFilesAndData(cacheDir: string, fileUris: Array<string>): Promise<Array<request.agent.FormItem>> {
            ...
            }
            // 创建文件上传后台任务
            async createBackgroundTask(fileUris: Array<string>) {if (this.context === undefined) {return;}// 获取上传urlthis.config.url = await urlUtils.getUrl(this.context);this.config.data = await this.getFilesAndData(this.context.cacheDir, fileUris);this.config.mode = request.agent.Mode.BACKGROUND;try {this.backgroundTask = await request.agent.create(this.context, this.config);await this.backgroundTask.start();let state = AppStorage.get<number>('backTaskState');if (state === BackgroundTaskState.PAUSE) {await this.backgroundTask.pause();}logger.info(TAG, `createBackgroundTask success`);} catch (err) {logger.error(TAG, `task  err, err  = ${JSON.stringify(err)}`);}
            }

              任务开始:

              await this.backgroundTask.start();

                任务暂停:

                async pause() {...if (this.backgroundTask === undefined) {return;}await this.backgroundTask.pause();
                }

                  任务继续

                  async resume() {...if (this.backgroundTask === undefined) {return;}await this.backgroundTask.resume();
                  }

                    本文主要引用参考HarmonyOS官方文档

                    相关文章:

                  • Beyond逆袭解码:三大战略构建DTC抗周期增长模型
                  • AI之光,点亮星途 :揭秘“智语心桥”,如何用科技为孤独症儿童架起沟通的桥梁
                  • 无线网络优化配置:让你的Wi-Fi更快更稳
                  • VSCode GitHub Copilot 安装与使用完全指南
                  • 设置标签(tag)并推送到GitHub
                  • 【linux知识】sftp配置免密文件推送
                  • ubuntu中上传项目至GitHub仓库教程
                  • 华为2025年校招笔试手撕真题教程(三)
                  • 【云原生安全】零信任与机密计算
                  • 视频监控管理平台EasyCVR结合AI分析技术构建高空抛物智能监控系统,筑牢社区安全防护网
                  • CyberSecAsia专访CertiK首席安全官:区块链行业亟需“安全优先”开发范式
                  • XMOS推出支持AES67标准的以太网音频解决方案——使高兼容性和低延迟专业音频传输及播放成为可能
                  • 记一次奇葩的错误,uniapp @tap点击失效
                  • Rust 学习笔记:生命周期
                  • uniapp使用sse连接后端,接收后端推过来的消息
                  • 深入掌握Node.js HTTP模块:从开始到放弃
                  • 在uni-app中修改上一个页面的值,可以通过多种方式实现,这里提供几种常见的方法:
                  • 解决 IntelliJ IDEA 配置文件中文被转义问题
                  • 杰发科技AC7840——CSE硬件加密模块使用(1)
                  • idea添加jar包
                  • 电商网站建设目的/百度店铺注册
                  • wordpress速度加快/宁波优化网站哪家好
                  • 北京网站案例/大连网站排名推广
                  • 长期供应小企业网站建设/百度关键词搜索量排名
                  • 比较好的做外贸网站/做推广哪个平台好
                  • 简单的j网站建设方案书/网站seo是什么意思