ImageDownloadComponent.ets 7.52 KB
import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
import { image } from '@kit.ImageKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import fs from '@ohos.file.fs';
import { DateTimeUtils, NetworkUtil, PermissionUtil } from 'wdKit';
import { PrivacySettingModel } from '../model/PrivacySettingModel';
import { TrackConstants, TrackingButton } from 'wdTracking';
import { faceDetector } from '@kit.CoreVisionKit';
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
import fileIo from '@ohos.file.fs';

const PERMISSIONS: Array<Permissions> = [
  'ohos.permission.READ_IMAGEVIDEO',
  'ohos.permission.WRITE_IMAGEVIDEO'
];

/*
 * saveButton参考文档
 * https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/savebutton-0000001820999677
 * */
@Component
export struct ImageDownloadComponent {
  @State image: PixelMap | undefined = undefined;
  @State photoAccessHelper: photoAccessHelper.PhotoAccessHelper | undefined = undefined; // 相册模块管理实例
  @State imageBuffer: ArrayBuffer | undefined = undefined; // 图片ArrayBuffer
  @Prop @Watch('onChangeUrl') url: string = ''
  @State isGranted: boolean = false
  @State name: string = ''

  build() {
    Column() {
      // Image($r('app.media.save_detail_img'))
      //   .width(24)
      //   .height(24)
      //   .margin({bottom:6})
      SaveButton({ icon: SaveIconStyle.FULL_FILLED, buttonType: ButtonType.Capsule })
        .iconSize(24)
        .backgroundColor(Color.Transparent)
        .iconColor(Color.White)
        .onClick(async () => {
          //console.info(`cj2024 onClick ${this.imageBuffer}`)
          if (this.imageBuffer !== undefined) {
            try {
              await this.saveImage(this.imageBuffer);
              promptAction.showToast({
                message: $r('app.string.image_request_success'),
                duration: 2000,
                alignment: Alignment.Center
              })
            } catch (error) {
              const err: BusinessError = error as BusinessError;
              //console.info(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
              promptAction.showToast({ message: '保存图片失败!' });
            }
          }
        })
    }

  }

  aboutToAppear(): void {
    // 注册监听网络连接
    let netStatus = NetworkUtil.isNetConnected()
    if (netStatus) {
      // 有网络
      this.onChangeUrl()
    }

  }

  async onChangeUrl(): Promise<void> {
    //console.info(`cj2024 图片下载 ${this.url}`)
    const context = getContext(this) as common.UIAbilityContext;
    const atManager = abilityAccessCtrl.createAtManager();
    await atManager.requestPermissionsFromUser(context, PERMISSIONS);
    this.getPicture();
  }

  /**
   * 通过http的request方法从网络下载图片资源
   */
  async getPicture() {
    // 每一个httpRequest对应一个HTTP请求任务,不可复用
    let httpRequest = http.createHttp();
    // 用于订阅HTTP响应头事件
    httpRequest.on('headersReceive', (header: Object) => {
      //console.info('header: ' + JSON.stringify(header));
    });
    // 用于订阅HTTP流式响应数据接收事件
    let res = new ArrayBuffer(0);
    httpRequest.on('dataReceive', (data: ArrayBuffer) => {
      const newRes = new ArrayBuffer(res.byteLength + data.byteLength);
      const resView = new Uint8Array(newRes);
      resView.set(new Uint8Array(res));
      resView.set(new Uint8Array(data), res.byteLength);
      res = newRes;
      // //console.info('dataReceive res length: ' + res.byteLength);
    });
    // 用于订阅HTTP流式响应数据接收完毕事件
    httpRequest.on('dataEnd', () => {
      this.transcodePixelMap(res);
      // 判断网络获取到的资源是否为ArrayBuffer类型
      //console.info(`dataEnd getPicture ${res}`)
      if (res instanceof ArrayBuffer) {
        //console.info(`dataEnd getPicture`)
        this.imageBuffer = res as ArrayBuffer;
      }
      //console.info('No more data in response, data receive end');
    });
    httpRequest.requestInStream(this.url,
      (error: BusinessError, data: number) => {
        if (error) {
          // 下载失败时弹窗提示检查网络,不执行后续逻辑
          promptAction.showToast({
            message: $r('app.string.image_request_fail'),
            duration: 2000
          })
          //console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);
          return;
        }
        // 取消订阅HTTP响应头事件
        httpRequest.off('headersReceive');
        // 取消订阅HTTP流式响应数据接收事件
        httpRequest.off('dataReceive');
        // 取消订阅HTTP流式响应数据接收完毕事件
        httpRequest.off('dataEnd');
        // 当该请求使用完毕时,调用destroy方法主动销毁
        httpRequest.destroy();
      }
    )
  }

  /**
   * 使用createPixelMap将ArrayBuffer类型的图片装换为PixelMap类型
   * @param data:网络获取到的资源
   */
  transcodePixelMap(data: ArrayBuffer) {
    const imageData: ArrayBuffer = data;
    // 通过ArrayBuffer创建图片源实例。
    const imageSource: image.ImageSource = image.createImageSource(imageData);
    const options: image.InitializationOptions = {
      'alphaType': 0, // 透明度
      'editable': false, // 是否可编辑
      'pixelFormat': 3, // 像素格式
      'scaleMode': 1, // 缩略值
      'size': { height: 100, width: 100 }
    }; // 创建图片大小

    // 通过属性创建PixelMap
    imageSource.createPixelMap(options).then((pixelMap: PixelMap) => {
      this.image = pixelMap;
    });
  }

  /**
   * 保存ArrayBuffer到图库
   * @param buffer:图片ArrayBuffer
   * @returns
   */
  async saveImage(buffer: ArrayBuffer | string): Promise<void> {
    //console.info(`cj2024 saveImage buffer ${buffer}`)
    if (!this.isGranted) {
      //跳转权限设置
      // const permissionUtil = new PermissionUtil();
      PermissionUtil.reqPermissionsFromUser(['ohos.permission.READ_MEDIA'], this).then((res) => {
        this.isGranted = res;
      });
    } else {
      // PermissionUtil.openPermissionsInSystemSettings(this);
    }


    const context = getContext(this) as common.UIAbilityContext; // 获取getPhotoAccessHelper需要的context
    // const helper = photoAccessHelper.getPhotoAccessHelper(context); // 获取相册管理模块的实例
    // const uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg'); // 指定待创建的文件类型、后缀和创建选项,创建图片或视频资源
    // //console.info(`cj2024 saveImage uri ${uri}`)
    // const file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    // await fs.write(file.fd, buffer);
    // await fs.close(file.fd);
    let media = mediaLibrary.getMediaLibrary(context);
    let publicPath = await media.getPublicDirectory(mediaLibrary.DirectoryType.DIR_IMAGE);
    let picName = DateTimeUtils.getCurDate(DateTimeUtils.PATTERN_DATE_TIME_DEFAULT) + '.jpg'
    // //console.info(`cj2024 saveImage time ${picName}`)
    let asset = await media.createAsset(mediaLibrary.MediaType.IMAGE, picName, publicPath);

    if (asset) {
      let fd = await asset.open('rw');
      await fileIo.write(fd, buffer);
      await asset.close(fd);
      promptAction.showToast({ message: '已保存至相册!' });
    } else {
      promptAction.showToast({ message: '保存图片失败!' });
      throw new Error('Failed to create asset');
    }
  }
}