HarmonyOS实战:GIF图下载突破5M限制保存到相册
前言 最近在鸿蒙项目开发过程中,测试提出图片预览时无法下载的 bug,这么简单的功能怎么会有问题。一开始还以为是手机的问题或者网络不好,拿到测试机复现问题的时候发现下载的 Gif 图确实无法下载成功,报了个2300023 错误码,查看鸿蒙文档才发现图片下载时使用的是 http 请求,但是 http 请求限制了流的大小为 5M,而 Gif 的大小超过了限制,本篇文章将详细带你一步步解决这个问题,同时解决图片链接为 png 但是下载后是 Gif 图的问题,建议点赞收藏! 实现效果
需求分析 ● 图片下载突破最大 5M 限制。 ● 图片链接以 jpg结尾但是张 GIF。 技术实现 下载突破 5M 限制 官方的 http 请求对数据流大小有限制,最大为 5M,所以需要采用其他方案实现下载功能,这里采用 HttpRequest的requestInStream 对数据流进行分段下载。
-
首先创建 HttpRequest,这里使用 http 创建。 let httpRequest = http.createHttp();
-
调用 http.requestInstream 方法,根据返回码来判断链接是否请求成功,同时需要配置一些网络请求参数。可根据需要配置。 let streamInfo: http.HttpRequestOptions = { method: http.RequestMethod.GET, // 可选,默认为http.RequestMethod.GET // 开发者根据自身业务需要添加header字段 header: { 'Content-Type': 'application/json' }, expectDataType: http.HttpDataType.ARRAY_BUFFER, // 可选,指定返回数据的类型 usingCache: true, // 可选,默认为true priority: 1, // 可选,默认为1 connectTimeout: 60000, // 可选,默认为60000ms readTimeout: 60000, // 可选,默认为60000ms。若传输的数据较大,需要较长的时间,建议增大该参数以保证数据传输正常终止 } httpRequest.requestInStream(imageUrl, streamInfo).then((data: number) => { if (data == 200) { } else { fail() } })
-
订阅数据接收方法 dataReceive,由于数据流是分段下载所有需要额外定义一个 ArrayBuffer 用来接收完整的数据流。 let res = new ArrayBuffer(0); httpRequest.on('dataReceive', (data: ArrayBuffer) => { const newRes = new ArrayBuffer(res.byteLength + data.byteLength); const resView = new Uint8Array(newRes); resView.set(new Uint8Array(res)); resView.set(new Uint8Array(data), res.byteLength); res = newRes;
});
-
当图片分段下载时,需要根据订阅dataEnd 方法来判断所有的数据流接收完成,同时将完整的数据流回调出去。 httpRequest.on('dataEnd', () => { success(res) })
-
当网络请求结束时,需要取消所有订阅的事件。 httpRequest.off('headerReceive') httpRequest.off('dataEnd') � 判断图片类型 一般图片链接是以具体图片类型结尾,如 .png,.jep 等场景类型,但是也有没有直接给出图片类型的链接,甚至还有图片链接以 jep 结尾,但是图片确实 GIF 格式。这时如果仅仅根据链接判断容易判断失误。 1.先需要创建一个PixelMap,这里根据网络请求返回的 ArrayBuffer 来创建 PixelMap。 let imageSource: image.ImageSource = image.createImageSource(buffer); class tmp { height: number = 100 width: number = 100 }; let options: Record<string, number | boolean | tmp> = { 'alphaType': 0, // 透明度 'editable': false, // 是否可编辑 'pixelFormat': 3, // 像素格式 'scaleMode': 1, // 缩略值 'size': { height: 100, width: 100 } }; // 创建图片大小 imageSource.createPixelMap(options).then((pixelMap: PixelMap) => {
})
�2. 根据返回的 pixelMap 获取图片的ImageInfo。 pixelMap.getImageInfo().then(async (info: image.ImageInfo) => {
}).catch((err: BusinessError) => {
})
�3. 根据返回的 image.ImageInfo 获取图片的 mimeType,如果是 GIF 图,则为 image/gif,如果时 png 则为 image/png。然后再将图片保存至相册时,指定图片的正确类型即可。 const context = getContext() as common.UIAbilityContext; // 获取getPhotoAccessHelper需要的context const helper = photoAccessHelper.getPhotoAccessHelper(context); // 获取相册管理模块的实例 const uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, info.mimeType == "image/gif"?'gif':'jpg'); // 指定待创建的文件类型、后缀和创建选项,创建图片或视频资源 const file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); let r = await fs.write(file.fd, buffer); await fs.close(file.fd);
这里为了方便处理,仅处理 GIF 的类型,其他类型都是 png。 � 总结 日常使用 http 请求能满足大部分的场景,但是遇到 GIF 图体积较大时,就必须使用分段式下载。将图片保存时必须获取图片信息的真实类型才能保存成功,否则很容易将 GIF 图保存成普通的图片,这一点在日常开发中特别重要,已经学会了的小伙伴,赶快动手试试吧。
- 0回答
- 0粉丝
- 0关注
- HarmonyOS实战:一招搞定保存图片到相册
- 鸿蒙保存图片到相册
- 鸿蒙安全控件之保存控件简介
- 【待更新】OpenHarmony——家庭云相册
- HarmonyOS NEXT 头像制作项目系列教程之 --- 组件快照与头像保存
- 【HarmonyOS】鸿蒙中如何获取用户相册图片?photoAccessHelper.PhotoViewPicker
- 鸿蒙Next文件下载RCP单线程和多线程使用对比
- 25.Harmonyos Next仿uv-ui 组件 NumberBox 步进器组件范围限制
- 鸿蒙Next如何实现打开相册选图片功能?
- harmony-utils之PhotoHelper,相册相关工具类
- ArkUI-X跨平台开发能力解析:优势与限制场景
- harmony-utils之PickerUtil,拍照、文件选择和保存,工具类
- ##DevEco Studio##如何让模拟器里有图片?【图片下载法】
- 68.Harmonyos NEXT 图片预览组件应用实践(一):相册与社交场景
- (八五)HarmonyOS Design 在智能穿戴设备中的实践:应对设计限制与优化小屏幕体验