HarmonyOS Next 保存图片数据到系统文件

在鸿蒙应用开发中,保存图片数据到系统相册通常需要申请 basic 权限。然而,某些应用可能不希望申请额外的权限,或者没有充分的理由申请 basic 权限。在这种情况下,开发者可以选择将图片数据保存到系统文件中,而不是直接保存到相册。本文将详细介绍如何在鸿蒙开发中实现这一功能,包括图片数据的压缩处理、文件命名、保存路径选择以及文件写入操作。


1. 图片数据的压缩处理

在保存图片之前,通常需要对图片数据进行压缩处理,以减少文件大小并优化存储空间。鸿蒙系统提供了 image.ImagePacker 类,可以方便地对图片数据进行压缩。

以下是一个图片压缩的示例代码:

let bitmap: ArrayBuffer; // 图片数据
let packer: image.ImagePacker = image.createImagePacker();
let packerData = await packer.packing(bitmap, {
    format: 'image/jpeg', // 图片格式
    quality: 90 // 图片质量(0-100)
});

在这个示例中,bitmap 是原始的图片数据,packer.packing 方法将图片数据压缩为 JPEG 格式,并设置图片质量为 90。


2. 生成唯一的文件名称

为了避免文件重名,我们可以根据当前时间生成一个唯一的文件名称。以下是一个生成文件名称的示例代码:

let date = new Date();
let year: string = date.getFullYear().toString();
let month: string = this.addSpaceZero(date.getMonth() + 1);
let day: string = this.addSpaceZero(date.getDate());
let hours: string = this.addSpaceZero(date.getHours());
let minutes: string = this.addSpaceZero(date.getMinutes());
let seconds: string = this.addSpaceZero(date.getSeconds());
let imageTitle: string = 'IMG_' + year + month + day + '_' + hours + minutes + seconds + '.jpg';
hilog.info(0x0000, `saveQRNew imageTitle: ${imageTitle}`, '%{public}s');

// 补零函数
addSpaceZero(timeNum: number): string {
    return timeNum < 10 ? '0' + timeNum.toString() : timeNum.toString();
}

在这个示例中,imageTitle 是根据当前时间生成的唯一文件名,格式为 IMG_YYYYMMDD_HHMMSS.jpg


3. 保存图片到系统文件

鸿蒙系统提供了 picker.PhotoSaveOptionspicker.PhotoViewPicker 类,用于选择保存路径并将图片数据写入文件。以下是一个保存图片的示例代码:

// 图片保存时的选项设置
let photoSaveOptions = new picker.PhotoSaveOptions();
photoSaveOptions.newFileNames = [imageTitle]; // 设置文件名

// 获取上下文并创建 PhotoViewPicker 实例
let abilityContext = getContext() as common.UIAbilityContext;
let photoPicker = new picker.PhotoViewPicker(abilityContext);

// 保存图片
photoPicker.save(photoSaveOptions).then((photoSaveResult: Array<string>) => {
    hilog.info(0x0000, `photoPicker save success, uri: ${JSON.stringify(photoSaveResult)}`, '%{public}s');
    let uri: string = photoSaveResult[0] || '';

    // 将图片数据写入文件
    let file = fs.openSync(uri, fs.OpenMode.WRITE_ONLY | fs.OpenMode.CREATE);
    fs.writeSync(file.fd, packerData);
    fs.closeSync(file.fd);
}).catch((err: BusinessError) => {
    hilog.info(0x0000, `photoPicker save fail, err: ${JSON.stringify(err)}`, '%{public}s');
});

在这个示例中:

  1. photoSaveOptions 用于设置保存文件的名称。
  2. photoPicker.save 方法用于选择保存路径并返回文件的 URI。
  3. fs.openSyncfs.writeSync 用于将压缩后的图片数据写入文件。

4. 注意事项

在实际开发中,需要注意以下几点:

(1)文件路径的合法性

确保生成的 URI 是合法的文件路径,避免写入失败。

(2)错误处理

在文件操作过程中,可能会遇到各种错误(如权限不足、存储空间不足等),需要捕获并处理这些错误。

(3)性能优化

如果图片数据较大,建议使用异步方式写入文件,避免阻塞主线程。


5. 完整代码示例

以下是一个完整的代码示例,包括图片压缩、文件命名和保存操作:

import image from '@ohos.multimedia.image';
import picker from '@ohos.file.picker';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';

async function saveImageToFile(bitmap: ArrayBuffer) {
    // 图片压缩
    let packer: image.ImagePacker = image.createImagePacker();
    let packerData = await packer.packing(bitmap, {
        format: 'image/jpeg',
        quality: 90
    });

    // 生成文件名
    let date = new Date();
    let year: string = date.getFullYear().toString();
    let month: string = addSpaceZero(date.getMonth() + 1);
    let day: string = addSpaceZero(date.getDate());
    let hours: string = addSpaceZero(date.getHours());
    let minutes: string = addSpaceZero(date.getMinutes());
    let seconds: string = addSpaceZero(date.getSeconds());
    let imageTitle: string = 'IMG_' + year + month + day + '_' + hours + minutes + seconds + '.jpg';
    hilog.info(0x0000, `saveQRNew imageTitle: ${imageTitle}`, '%{public}s');

    // 保存图片
    let photoSaveOptions = new picker.PhotoSaveOptions();
    photoSaveOptions.newFileNames = [imageTitle];
    let abilityContext = getContext() as common.UIAbilityContext;
    let photoPicker = new picker.PhotoViewPicker(abilityContext);

    photoPicker.save(photoSaveOptions).then((photoSaveResult: Array<string>) => {
        hilog.info(0x0000, `photoPicker save success, uri: ${JSON.stringify(photoSaveResult)}`, '%{public}s');
        let uri: string = photoSaveResult[0] || '';
        let file = fs.openSync(uri, fs.OpenMode.WRITE_ONLY | fs.OpenMode.CREATE);
        fs.writeSync(file.fd, packerData);
        fs.closeSync(file.fd);
    }).catch((err: BusinessError) => {
        hilog.info(0x0000, `photoPicker save fail, err: ${JSON.stringify(err)}`, '%{public}s');
    });
}

// 补零函数
function addSpaceZero(timeNum: number): string {
    return timeNum < 10 ? '0' + timeNum.toString() : timeNum.toString();
}

6. 总结

通过以上步骤,我们可以在鸿蒙开发中实现将图片数据保存到系统文件的功能,而无需申请 basic 权限。这种方式不仅简化了权限管理,还能满足某些特定场景的需求。希望本文的介绍能为您的开发工作提供帮助!

posted @ 2025-03-20 14:33  水滴石轩  阅读(133)  评论(0)    收藏  举报