import fileIo from '@ohos.fileio';
import photoAccessHelper from '@ohos.file.photoAccessHelper';
import fileUri from '@ohos.file.fileuri';
import promptAction from '@ohos.promptAction';
import image from '@ohos.multimedia.image';
import componentSnapshot from '@ohos.componentSnapshot';
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common';
@Component
export struct SaveImageComponent {
private controller: CustomDialogController;
// 需要申请的权限
private readonly requiredPermissions: Permissions[] = [
'ohos.permission.READ_IMAGEVIDEO',
'ohos.permission.WRITE_IMAGEVIDEO'
];
async saveImage() {
try {
// 1. 申请必要权限
await this.requestPermissions();
// 2. 截图并转换为二进制流
const arrayBuffer = await this.captureComponent();
// 3. 保存图片到应用沙箱
const imagePath = await this.saveToSandbox(arrayBuffer);
// 4. 保存到系统相册
await this.saveToGallery(imagePath);
// 5. 显示成功提示
promptAction.showToast({
message: '图片保存成功',
duration: 2000
});
} catch (error) {
console.error('图片保存失败:', JSON.stringify(error));
promptAction.showToast({
message: `保存失败: ${error.message || '未知错误'}`,
duration: 3000
});
} finally {
// 无论成功失败都关闭弹窗
this.controller.close();
}
}
// 申请必要权限
private async requestPermissions(): Promise<void> {
try {
const context = getContext(this) as common.UIAbilityContext;
const atManager = abilityAccessCtrl.createAtManager();
const grantStatus = await atManager.requestPermissionsFromUser(
context,
this.requiredPermissions
);
// 检查所有权限是否都授予
const allGranted = this.requiredPermissions.every(permission => {
return grantStatus.authResults[permission] === 0;
});
if (!allGranted) {
throw new Error('所需权限未完全授予');
}
} catch (error) {
console.error('权限申请失败:', JSON.stringify(error));
throw new Error('权限不足,无法保存图片');
}
}
// 截图组件并转换为二进制流
private async captureComponent(): Promise<ArrayBuffer> {
try {
const imgMsg = await componentSnapshot.get('share');
const imagePacker = image.createImagePacker();
return await imagePacker.packToData(imgMsg, {
format: 'image/jpeg',
quality: 98
});
} catch (error) {
console.error('截图失败:', JSON.stringify(error));
throw new Error('截图生成失败');
}
}
// 保存图片到应用沙箱
private async saveToSandbox(arrayBuffer: ArrayBuffer): Promise<string> {
let fileFd: number | null = null;
try {
const context = getContext(this);
const timestamp = new Date().getTime();
const imagePath = `${context.cacheDir}/screenshot_${timestamp}.jpeg`;
// 创建文件并获取文件描述符
fileFd = fileIo.openSync(imagePath,
fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE
);
// 写入数据
const bytesWritten = fileIo.writeSync(fileFd, arrayBuffer);
if (bytesWritten <= 0) {
throw new Error('图片写入失败');
}
return imagePath;
} catch (error) {
console.error('沙箱保存失败:', JSON.stringify(error));
throw new Error('图片保存到临时位置失败');
} finally {
// 确保文件描述符关闭
if (fileFd !== null) {
fileIo.closeSync(fileFd);
}
}
}
// 保存到系统相册
private async saveToGallery(imagePath: string): Promise<void> {
try {
const context = getContext(this);
const uri = fileUri.getUriFromPath(imagePath);
// 创建图片保存请求
const photoRequest =
photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(context, uri);
if (!photoRequest) {
throw new Error('创建图片保存请求失败');
}
const photoHelper = photoAccessHelper.getPhotoAccessHelper(context);
// 应用更改(保存图片)
await photoHelper.applyChanges([photoRequest]);
} catch (error) {
console.error('保存到相册失败:', JSON.stringify(error));
throw new Error('图片保存到相册失败');
}
}
}
添加权限申请:在 module.json5 中添加:
"requestPermissions": [
{
"name": "ohos.permission.READ_IMAGEVIDEO"
},
{
"name": "ohos.permission.WRITE_IMAGEVIDEO"
}
]
在UI中使用:
@Entry
@Component
struct MyComponent {
private saveDialogController: CustomDialogController | null = null;
build() {
Button('保存图片')
.onClick(() => {
this.saveDialogController = new CustomDialogController({
builder: SaveImageComponent({ controller: this.saveDialogController }),
});
this.saveDialogController.open();
})
}
}
简写(权限需要自己配置)
controller: CustomDialogController
async saveImage(){
//1.截图组件变成二进制流
//1.1 组件信息
//除了id要改其他的代码都可以原封不动的复用
const imgMsg = await componentSnapshot.get('share')
//1.2 创建imagePacker对象实例
const imagePacker = image.createImagePacker()
//1.3 将组件截图变成二进制流
const arrayBuffer = await imagePacker.packToData(imgMsg,{format:'image/jpeg', quality: 98 })
//2.将图片存储到沙箱
//2.1获取context对象
const ctx = getContext(this)
//2.2生成一个唯一一个的图片路径
const imagePath = ctx.cacheDir + '/' + Date.now() +'.jpeg'
//2.3创建文件
// 打开一个未创建的图片,让他具备创建和读写能力
// 参数1: imagePath 文件的路径
// 参数2: 因为还没有文件 fileIo.OpenMode.CREATE 所以先创建 fileIo.OpenMode.READ_WRITE 并设置读写能力
const file = fileIo.openSync(imagePath,fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
//2.4二进制写入沙箱
fileIo.writeSync(file.fd,arrayBuffer)
fileIo.closeSync(file.fd)
//3.从沙箱目录拿到图片保存到相册
//3.1获取uri地址
const uri = fileUri.getUriFromPath(imagePath)
//3.2获取资源文件请求
const photoRequest = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(ctx, uri)
//3.3创建获取相册实例
const photoHelper = photoAccessHelper.getPhotoAccessHelper(ctx)
//3.4保存到相册
photoHelper.applyChanges(photoRequest)
//3.5弹窗提示
promptAction.showToast({ message: '保存成功' })
//4.关闭弹框
this.controller.close()
}

用以前的demo试下,ok没有问题~~
875

被折叠的 条评论
为什么被折叠?



