【HarmonyOS】SaveButton组件把图片显示到相册中的方法demo,支持组件截图、url网络图片、base64格式图片。

注意事项:1、不支持自定义SaveButton样式。2、下载按钮被遮挡一部分,也无法保存到相册。


【HarmonyOS】鸿蒙SaveButton保存图片_鸿蒙

import photoAccessHelper from '@ohos.file.photoAccessHelper';
import fs from '@ohos.file.fs';
import { common } from '@kit.AbilityKit';
import { componentSnapshot, promptAction } from '@kit.ArkUI';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { http } from '@kit.NetworkKit';
import { util } from '@kit.ArkTS';

@Entry
@Component
struct Page09 {
  inviteQrCodeID: string = "inviteQrCodeID"
  @State imageUrl: string =
    "https://img1.baidu.com/it/u=1268271089,1175168242&fm=253&fmt=auto&app=120&f=JPEG?w=506&h=500"
  @State base64Str: string =
    'data:image/png;base64,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'

  build() {
    Scroll() {
      Column({ space: 10 }) {
        Column({ space: 10 }) {
          Text('下载组件截图图片到相册')

          Column() {
            Column() {
              Text('标题测试').fontSize('36lpx').height('120lpx').fontColor("#2E2E2E")
              QRCode('https://www.huawei.com/')
                .width('300lpx')
                .height('300lpx')
                .margin({ top: '25lpx' })
                .draggable(false)
                .width(140)
                .height(140)
            }.padding({ left: '42lpx', right: '42lpx', bottom: '20lpx' })

            Text('点按下载保存至相册')
              .textAlign(TextAlign.Center)
              .padding({ left: '125lpx', right: '125lpx' })
              .fontColor("#4B4B4B")
              .fontSize('32lpx')
              .margin({ bottom: '70lpx' })
          }
          .id(this.inviteQrCodeID)
          .padding('20lpx')
          .margin({ top: '30lpx', bottom: '30lpx' })
          .backgroundColor(Color.White)
          .borderRadius('30lpx')
          .alignItems(HorizontalAlign.Center)
          .justifyContent(FlexAlign.Center)

          SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
            if (result === SaveButtonOnClickResult.SUCCESS) {
              const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
              // 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
              let helper = photoAccessHelper.getPhotoAccessHelper(context);
              try {
                // onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
                let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
                // 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
                let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
                componentSnapshot.get(this.inviteQrCodeID).then((pixelMap) => {
                  let packOpts: image.PackingOption = { format: 'image/png', quality: 100 }
                  const imagePacker: image.ImagePacker = image.createImagePacker();
                  return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
                    imagePacker.release(); //释放
                    fs.close(file.fd);
                    promptAction.showToast({
                      message: '图片已保存至相册',
                      duration: 2000
                    });
                  });
                })
              } catch (error) {
                const err: BusinessError = error as BusinessError;
                console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
              }

            } else {
              promptAction.showToast({
                message: '设置权限失败!',
                duration: 2000
              });
            }
          })
        }.borderWidth(1).borderStyle(BorderStyle.Dotted).backgroundColor(Color.Pink).padding('50lpx')

        Column({ space: 10 }) {
          Text('下载网络图片到相册')
          /**
           * 需要在  src/main/module.json5
           * 添加网络权限
           * {
           "module": {
           "requestPermissions": [
           {
           "name": "ohos.permission.INTERNET"
           },
           ],
           */
          Image(this.imageUrl).width('100lpx')

          SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
            if (result === SaveButtonOnClickResult.SUCCESS) {
              const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
              // 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
              // savePhotoToGallery(context);
              let helper = photoAccessHelper.getPhotoAccessHelper(context);
              try {
                http.createHttp().request(
                  this.imageUrl,
                  { expectDataType: http.HttpDataType.ARRAY_BUFFER }
                ).then(async (res) => {
                  console.info('res', JSON.stringify(res))
                  // 将图片资源转为像素图(PixelMap)
                  let pixelMap = await image.createImageSource(res.result as ArrayBuffer).createPixelMap()

                  // onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
                  let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
                  // 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
                  let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
                  let packOpts: image.PackingOption = { format: 'image/png', quality: 100 }
                  const imagePacker: image.ImagePacker = image.createImagePacker();
                  return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
                    imagePacker.release(); //释放
                    fs.close(file.fd);
                    promptAction.showToast({
                      message: '图片已保存至相册',
                      duration: 2000
                    });
                  });
                }).catch(() => {
                  console.info('catch')
                })
              } catch (error) {
                const err: BusinessError = error as BusinessError;
                console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
              }

            } else {
              promptAction.showToast({
                message: '设置权限失败!',
                duration: 2000
              });
            }
          })
        }.borderWidth(1).borderStyle(BorderStyle.Dotted).backgroundColor(Color.Pink).padding('50lpx')

        Column({ space: 10 }) {
          Text('下载base64图片到相册')
          Text('注意1:有些base64的格式图片显示不出来,\n是因为前缀没加data:image/png;base64,').textAlign(TextAlign.Center)
          Text("注意2:下载到相册的base64字符串不能有'data:image/jpeg;base64,'这样的前缀。所以我这里用正则去掉了前缀").textAlign(TextAlign.Center)
          SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
            if (result === SaveButtonOnClickResult.SUCCESS) {
              const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
              // 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
              // savePhotoToGallery(context);
              let helper = photoAccessHelper.getPhotoAccessHelper(context);
              try {
                // 正则表达式用于匹配 "data:image/*;base64," 这样的前缀
                const prefixRegex = /^data:image\/[a-zA-Z]+;base64,/;
                // 使用 replace 方法去除匹配到的前缀
                let base64String = this.base64Str.replace(prefixRegex, '')
                let buffer: ArrayBuffer =
                  new util.Base64Helper().decodeSync(base64String, util.Type.MIME).buffer as ArrayBuffer;
                let imageSource = image.createImageSource(buffer);
                let pixelMap = await imageSource.createPixelMap({ editable: true });

                let opts: image.PackingOption = { format: "image/jpeg", quality: 100 };
                // onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
                let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
                // 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
                let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
                let packOpts: image.PackingOption = { format: 'image/png', quality: 100 }
                const imagePacker: image.ImagePacker = image.createImagePacker();
                return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
                  imagePacker.release(); //释放
                  fs.close(file.fd);
                  promptAction.showToast({
                    message: '图片已保存至相册',
                    duration: 2000
                  });
                });
              } catch (error) {
                const err: BusinessError = error as BusinessError;
                console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
              }

            } else {
              console.info(`result:${JSON.stringify(result)}`)
              promptAction.showToast({
                message: '设置权限失败!',
                duration: 2000
              });
            }
          })
        }
        .borderWidth(1).borderStyle(BorderStyle.Dotted).backgroundColor(Color.Pink).padding('50lpx')

      }.width('100%')
    }.width('100%')
  }
}

注意事项:

1、样式不支持自定义图标,试过用opacity修改透明度,然后添加背景来实现自定义样式,结果也失败了,opacity(1)点击生效,opacity(0.9)后点击按钮就不生效了。

参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-arkui-301-V5

2、如果带Scroll时,下载按钮被遮挡一部分,也无法保存到相册。

比如下面这样遮挡一点点下载按钮后,点击就没办法保存到相册了。

【HarmonyOS】鸿蒙SaveButton保存图片_鸿蒙_02

【参考方案】

1、官方文档:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-security-components-savebutton-V5

2、PixelMap和base64的相互转换

参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-image-15-V5