HarmonyOS:将 media里的图片保存到相册
·
一、需求场景
app内分享固定图片,可以将图片保存到相册里
二、实现方案
- 从 resources/media 获取图片的 ArrayBuffer
- 将ArrayBuffer转换成PixelMap
- pixelMap 生成图片 保存到应用沙箱里
使用image.createImagePacker()和packer.packToData(pixelMap, packOpts)- 使用fileIo将图片写入到指定沙箱路径
- 使用弹窗授权保存媒体库资源(phAccessHelper.showAssetsCreationDialog), 将应用沙箱图片保存到系统相册
三、实践
FileUtil.ets文件代码
export class FileUtil {
/**
*
* @param fileUri 文件的应用沙箱路径
*/
static deleteFile(fileUri?: string) {
if (!fileUri) {
console.log(`沙箱路径 fileUri 参数值 ${fileUri} 不正确`)
return
}
fileIo.access(fileUri, fileIo.AccessModeType.EXIST).then((accessRes: boolean) => {
if (accessRes) {
fileIo.unlink(fileUri, (err: BusinessError) => {
if (err) {
console.error(`文件:${fileUri} , 删除 失败. Code: ${err.code}, message: ${err.message}`);
} else {
console.info(`文件:${fileUri} , 删除 成功`);
}
});
} else {
console.log(`文件 ${fileUri} 不存在`)
}
}).catch((err: BusinessError) => {
console.error(
`deleteFile 删除文件 Failed to access. Code: ${err.code}, message: ${err.message} , fileUri: ${fileUri}`);
});
}
}
PhotoViewPickerUtil.ets文件代码
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { common } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { dataSharePredicates } from '@kit.ArkData';
import util from '@ohos.util';
import { FileUtil } from './FileUtil';
export class PhotoViewPickerUtil {
// 将已编码的图片 ArrayBuffer 转换为 PixelMap
static async bufferToPixelMap(buffer: ArrayBuffer): Promise<image.PixelMap | undefined> {
// 1. 通过 ArrayBuffer 创建 ImageSource
const imageSource: image.ImageSource = image.createImageSource(buffer);
// 2. 解码创建 PixelMap
const pixelMap: image.PixelMap = await imageSource.createPixelMap();
// 3. 释放 ImageSource 资源
imageSource.release();
return pixelMap;
}
/**
* pixelMap 生成图片 保存到应用沙箱里
* @param uiContext
* @param pixelMap
* @param fileName
*/
static async savaPixelMap(uiContext: common.UIAbilityContext, pixelMap: image.PixelMap,
fileName?: string): Promise<string | null> {
const packer = image.createImagePacker();
const packOpts: image.PackingOption = { format: 'image/png', quality: 100 };
try {
const arrayBuffer = await packer.packToData(pixelMap, packOpts);
if (!fileName) {
const timeStamp = Date.now();
// const random = Math.random()
fileName = "IMG_" + timeStamp + ".png"
}
let filePath = `${uiContext.tempDir}/${fileName}`;
const file = fileIo.openSync(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
fileIo.writeSync(file.fd, arrayBuffer);
fileIo.closeSync(file);
console.log("pixelMap 生成图片 沙箱路径:", filePath)
return filePath
} catch (error) {
console.error(`pixelMap 生成图片 保存到应用沙箱里 失败, error: ${JSON.stringify(error)}`);
}
return null
}
/**
* 使用弹窗授权保存媒体库资源 将应用沙箱图片保存到系统相册
*/
static async saveIamgeToPicture(
srcFileUri: string,
context: common.UIAbilityContext
): Promise<string> {
console.log("调用了 saveIamgeToPicture")
let phAccessHelper: photoAccessHelper.PhotoAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
let desFile: fileIo.File | null = null;
let srcFile: fileIo.File | null = null;
try {
// 指定要保存到应用程序沙盒目录中的图片的URI。
let srcFileUris: string[] = [
srcFileUri
];
const timeStamp = Date.now();
const fileName = "IMG_" + timeStamp
// 设置要保存的图片的参数:文件扩展名、图片类型、标题和子类型(后两者为可选)
let photoCreationConfigs: photoAccessHelper.PhotoCreationConfig[] = [
{
title: fileName, // This parameter is optional.
fileNameExtension: 'png',
photoType: photoAccessHelper.PhotoType.IMAGE,
subtype: photoAccessHelper.PhotoSubtype.DEFAULT,
}
];
console.info('沙箱 URI: ' + srcFileUri);
// 基于弹窗授权获取媒体库中的目标URI
let desFileUris: string[] =
await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
console.info('获取媒体库中的目标 URIs: ' + JSON.stringify(desFileUris));
// 将图片从沙盒目录写入媒体库中的目标URI。
desFile = await fileIo.open(desFileUris[0], fileIo.OpenMode.WRITE_ONLY);
srcFile = await fileIo.open(srcFileUri, fileIo.OpenMode.READ_ONLY);
await fileIo.copyFile(srcFile.fd, desFile.fd);
console.info('保存图片成功');
return '保存图片成功';
} catch (err) {
console.error(`保存图片失败 errCode is: ${err.code}, ${err.message}`);
return `保存图片失败 errCode is: ${err.code}, ${err.message}`;
} finally {
if (srcFile) {
fileIo.closeSync(srcFile);
FileUtil.deleteFile(srcFileUri)
}
if (desFile) {
fileIo.closeSync(desFile);
}
}
}
}
TestSavaImage.ets文件代码
import { common } from '@kit.AbilityKit';
import resourceManager from '@ohos.resourceManager';
import { PhotoViewPickerUtil } from '../../common/utils/PhotoViewPickerUtil';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
/*
将 media里的图片保存到相册
*/
@Entry
@ComponentV2
struct TestSavaImage {
context = this.getUIContext().getHostContext() as common.UIAbilityContext;
@Local message: string = 'Hello World';
/**
* 将 media里的图片保存到相册
*/
async saveImage() {
// 1. 从 resources/media 获取图片的 ArrayBuffer
const mgr: resourceManager.ResourceManager = this.context.resourceManager;
try {
const imageBuffer: Uint8Array = await mgr.getMediaContent($r('app.media.enablement_pic2'));
PhotoViewPickerUtil.bufferToPixelMap(imageBuffer.buffer as ArrayBuffer).then((pixelMap) => {
if (pixelMap) {
//保存到沙箱
PhotoViewPickerUtil.savaPixelMap(this.context, pixelMap).then((filelUri) => {
if (filelUri) {
// 保存到相册
PhotoViewPickerUtil.saveIamgeToPicture(filelUri, this.context).then((res) => {
promptAction.openToast({ message: res }).catch(() => {
})
})
}
})
}
})
} catch (error) {
const err = error as BusinessError
console.log("保存图片失败 异常信息 name :" + err.name + " , message:" + err.message + " , code:" + err.code)
}
}
build() {
Column({ space: 20 }) {
Image($r('app.media.enablement_pic2'))
.width('90%')
.objectFit(ImageFit.Contain)
.margin({ top: 40 })
Button("将media里的图片保存到相册").onClick(() => {
this.saveImage()
})
}
.height('100%')
.width('100%')
}
}
更多推荐


所有评论(0)