
回复
@toc
大家好,我是若城。写这个系列的目的是为了帮助大家在开发时能够快速地完成一些小功能的开发。需要注意的是,这个系列不会有过多的讲解以及复杂的演示,但可以保证开发者在使用时直接复制粘贴就可以将该功能实现。不过,需要申请权限的地方,还请开发者自己去申请,这个系列不会讲解过于基础的内容。
本文将介绍如何在HarmonyOS Next应用中实现从网络下载图片并保存到设备相册的功能。这是一个常见的需求,例如在图片浏览、社交媒体等应用中,用户希望能够保存喜欢的图片到本地相册。
import { abilityAccessCtrl, common } from '@kit.AbilityKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import fs from '@ohos.file.fs';
import { http } from '@kit.NetworkKit';
import { promptAction } from '@kit.ArkUI';
private appContext: common.Context = getContext(this);
private atManager = abilityAccessCtrl.createAtManager();
@State downLoadImg:boolean = false;
这些模块的作用:
AbilityKit
:用于权限管理MediaLibraryKit
:用于访问和管理相册fs
:文件系统操作NetworkKit
:网络请求ArkUI
:提供UI交互组件
// 下载按钮
Column() {
Image($r("app.media.downImg"))
.width(24)
.height(24)
Text('下载')
.fontSize(12)
.fontColor('#FFFFFF')
.margin({ top: 4 })
}
.onClick(() => {
if (this.downLoadImg){
promptAction.showToast({
message: '正在下载中,请稍后',
duration: 1000,
});
}else{
this.saveFile(this.dataList.pic_url)
}
})
.margin({ right: 32 })
功能讲解
点击按钮的过程在判断this.downLoadImg
是否为true
, 如果是true
,则表示 已经触发下载逻辑, 不需要再次下载, 否则 调用 函数this.saveFile
, 传递的参数 是网络图片的URL
// 保存图片到相册
async saveFile(url: string) {
this.downLoadImg = true;
//申请权限并保存图片到图库
try {
//申请相册管理模块权限'ohos.permission.WRITE_IMAGEVIDEO'
this.atManager.requestPermissionsFromUser(this.appContext, ['ohos.permission.WRITE_IMAGEVIDEO'])
.then(async () => {
//权限申请成功,保存到图库
let context = getContext();
//获取相册管理模块的实例,用于访问和修改相册中的媒体文件
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
// onClick触发后10秒内通过createAsset接口创建图片文件,10秒后createAsset权限收回
promptAction.showDialog({
title: "图片下载中....",
})
let uri = await phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
// 创建媒体文件
let file = fs.openSync(uri, fs.OpenMode.READ_WRITE || fs.OpenMode.CREATE);
let totalSize = 0;
let httpRequest = http.createHttp();
httpRequest.on("dataReceive", (data: ArrayBuffer) => {
let writeLen = fs.writeSync(file.fd, data);
totalSize = totalSize + writeLen;
});
httpRequest.requestInStream(url,
{ method: http.RequestMethod.GET, connectTimeout: 3000, }, httpCode => {
console.info('requestInStream HTTP CODE is', httpCode)
})
httpRequest.on("dataEnd", () => {
fs.close(file);
promptAction.showDialog({
title: "下载图片结束,并保存至相册",
message: `图片大小:${totalSize}字节`
})
this.downLoadImg = false;
})
})
} catch (err) {
console.error(`requestPermissionsFromUser call Failed! error: ${err.code}`);
this.downLoadImg = false;
}
}
权限申请:
atManager.requestPermissionsFromUser
申请WRITE_IMAGEVIDEO
权限,这是保存图片到相册所必需的创建媒体资源:
photoAccessHelper.getPhotoAccessHelper(context)
phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg')
,指定类型为图片,格式为jpg文件操作:
fs.openSync
打开文件,设置为读写模式并在不存在时创建fs.writeSync
将接收到的数据写入文件网络请求:
http.createHttp()
httpRequest.on("dataReceive", ...)
httpRequest.requestInStream
,适用于大文件下载httpRequest.on("dataEnd", ...)
用户交互:
promptAction.showDialog({ title: "图片下载中...." })
promptAction.showDialog({ title: "下载图片结束,并保存至相册", message: ... })
downLoadImg
防止重复下载需要注意的是, 这三段代码是一个整体, 开发者要整体上去看去了解, 就会理解有些变量定义的含义了 , 好~~ 下课