保存图片或音频到相册

介绍

        在HarmonyOS里面对于权限的要求是很严格的,在日常的开发中往往又有保存图片或者音频到本地的开发需求,因此我们可以使用非权限的替代方案实现功能,主要就是使用安全控件或者是授权弹框来实现资源的保存。

实现

安全控件

官方链接:文档中心

实现效果

代码实现
import { http } from '@kit.NetworkKit';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileIo } from '@kit.CoreFileKit';
import { promptAction } from '@kit.ArkUI';
import { photoAccessHelper } from '@kit.MediaLibraryKit';

@Entry
@Component
struct Index {
  @State url: string =
    'https://qcloud.dpfile.com/pc/TrdZpLN1zkXDV4oN2FH98LdVnvHj694NKQu0_KA3ul4eYxZWRPQ7CJuw-PqyZBS4.jpg'

  loadImageWithUrl(url: string) {
    let responseCode = http.ResponseCode;
    let OutData: http.HttpResponse;
    let imagePackerApi = image.createImagePacker();
    let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 98 };
    let pixelMap: PixelMap | undefined = undefined;
    // 确保网络正常
    http.createHttp().request(url, {
      method: http.RequestMethod.GET,
      connectTimeout: 60000,
      readTimeout: 60000
    },
      async (error: BusinessError, data: http.HttpResponse) => {
        if (error) {
          console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);
        } else {
          OutData = data;
          let code: http.ResponseCode | number = OutData.responseCode;
          if (responseCode.OK === code) {
            let imageData: ArrayBuffer = OutData.result as ArrayBuffer;
            let imageSource: image.ImageSource = image.createImageSource(imageData);

            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((pixelMap1: PixelMap) => {
              pixelMap = pixelMap1;
              pixelMap.getImageInfo().then((info: image.ImageInfo) => {
                console.info('info.width = ' + info.size.width);
              }).catch((err: BusinessError) => {
                console.error('Failed ' + err);
              })
              imagePackerApi.packing(pixelMap, packOpts).then(async (buffer: ArrayBuffer) => {
                try {
                  const context = getContext();
                  let helper = photoAccessHelper.getPhotoAccessHelper(context);
                  let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'png');
                  let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
                  // 写入文件
                  await fileIo.write(file.fd, buffer);
                  promptAction.showToast({ message: '已保存至相册!', alignment: Alignment.Center });
                  // 关闭文件
                  await fileIo.close(file.fd);
                } catch (error) {
                  console.error('error is ' + JSON.stringify(error));
                }
              }).catch((error: BusinessError) => {
                console.error('Failed to pack the image. And the error is: ' + error);
              })
              pixelMap.release();
            })
          }
        }
      }
    )
  }

  build() {
    Column({ space: 20 }) {
      Image(this.url)
        .width(100)
        .height(100)


      SaveButton({
        icon: SaveIconStyle.FULL_FILLED,
        text: SaveDescription.SAVE_IMAGE,
        buttonType: ButtonType.Normal
      })
        .onClick((_event, result) => {
          if (result === SaveButtonOnClickResult.SUCCESS) {
            this.loadImageWithUrl(this.url as string);
            // this.loadImageWithUrl(this.img as string);
          } else {
            promptAction.showToast({ message: '设置权限失败!', alignment: Alignment.Center });
          }
        })


    }
    .width('100%')
    .padding({ top: 50, left: 20 })
  }
}

授权弹框

官方链接:文档中心

实现效果

代码实现
import { request } from '@kit.BasicServicesKit'
import { fileIo, fileUri } from '@kit.CoreFileKit'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { promptAction } from '@kit.ArkUI'
import { Context } from '@kit.AbilityKit'

@Entry
@Component
struct Index {
  @State Img: string =
    'https://qcloud.dpfile.com/pc/h0jK_DfiFV_fQjL3CQpOVgRTnPIjwQlmZHNHjRv2n3Yrg3bZmogVH6Ln8ywR4Guo.jpg'
  @State filePath: string = ''
  context: Context = getContext(this)

  async downloadPicture() {
    // 设置沙箱路径
    let filePath = getContext().cacheDir + '/test' + Date.now() + '.png'
    // 创建下载任务
    const task = await request.downloadFile(getContext(), {
      // 设置图片的源地址
      url: this.Img,
      // 设置图片存储路径
      filePath: filePath
    })
    task.on('complete', async () => {
      this.filePath = filePath
      this.filePath = fileUri.getUriFromPath(filePath)
      let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(this.context);
      try {
        let srcFileUri = filePath;
        let srcFileUris: Array<string> = [
          fileUri.getUriFromPath(srcFileUri)
        ];
        let photoCreationConfigs: Array<photoAccessHelper.PhotoCreationConfig> = [
          {
            title: 'test', // 可选
            fileNameExtension: 'png',
            photoType: photoAccessHelper.PhotoType.IMAGE,
            subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选
          }
        ];
        let desFileUris: Array<string> =
          await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
        let desFile: fileIo.File =
          await fileIo.open(desFileUris[0], fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
        let srcFile: fileIo.File = await fileIo.open(srcFileUri, fileIo.OpenMode.READ_ONLY);
        await fileIo.copyFile(srcFile.fd, desFile.fd);
        fileIo.closeSync(srcFile);
        fileIo.closeSync(desFile);
        fileIo.rmdirSync(filePath)
        promptAction.showToast({ message: '保存成功!' })
      } catch (err) {
        console.error(`failed to create asset by dialog successfully errCode is: ${err.code}, ${err.message}`);
      }

    })
  }

  build() {
    Column({ space: 20 }) {
      Image(this.Img)
        .width(100)
        .height(100)

      Button('保存图片')
        .onClick(async () => {
          this.downloadPicture()
        })

    }
    .width('100%')
    .height('100%')
    .padding({ top: 50, left: 30 })
  }
}

总结

本文主要介绍了两种可以不用通过申请相册的读、写权限来实现保存图片的替代方案。在功能的实现方面,代码还是很简单,但是由于HarmonyOS对于权限的审核还是很严格,因此,还需要我们在实际的开发过程中,找到更多的可替代方案,希望大家多多交流,早日完善鸿蒙系统的生态!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值