HarmonyOS 使用photoAccessHelper.PhotoViewPicker选取图片后无法把选取的图片保存到沙箱路径下?

使用photoAccessHelper.PhotoViewPicker选取图片(或视频),根据资源uri将资源写入到沙箱路径下。photoAccessHelper.MediaAssetDataHandler接口的代理方法onDataPrepared中this是undefined,这样就导致无法获取到沙箱路径,无法把arraybuffer保存到沙箱路径下。

代码:

class MediaDataHandler implements photoAccessHelper.MediaAssetDataHandler<ArrayBuffer> {
  private toPath: string;

  constructor(toPath: string) {
    this.toPath = toPath;
  }

  onDataPrepared(data: ArrayBuffer, map?: Map<string, string>) {
    if (data === undefined) {
      console.error('Error occurred when preparing data');
      return;
    }
    console.info('on image data prepared');
    // 应用自定义对资源数据的处理逻辑
    // 这里this是undefined
    IO.writeContentsSync(this.toPath, data);
  }
}
阅读 624
1 个回答

在类最外层定义目标路径destPath赋值可以正常保存文件:

const context = getContext(this);
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
let destPath: string;

class MediaDataHandler implements photoAccessHelper.MediaAssetDataHandler<ArrayBuffer> {
  onDataPrepared(data: ArrayBuffer, map?: Map<string, string>) {
    if (data === undefined) {
      console.error('Error occurred when preparing data');
      return;
    }
    // 应用自定义对资源数据的处理逻辑
    // this undefined???
    const file = fs.openSync(destPath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
    fs.writeSync(file.fd, data);
    fs.fsyncSync(file.fd);
    fs.closeSync(file.fd);
  }
}

export class PhotoAccessPicker {
  static pickFile(saveDir: string, acceptTypes: photoAccessHelper.PhotoViewMIMETypes, resultHandler: (error?: BusinessError, fileName?: string|null) => void) {
    if (fs.accessSync(saveDir) === false || fs.statSync(saveDir).isDirectory() === false) {
      fs.mkdirSync(saveDir, true);
    }
    const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
    photoSelectOptions.MIMEType = acceptTypes; // 过滤选择媒体文件类型
    photoSelectOptions.maxSelectNumber = 1; // 选择媒体文件的最大数目

    let uris: Array<string> = [];
    const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
    photoViewPicker.select(photoSelectOptions).then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
      uris = photoSelectResult.photoUris;
      console.info('photoViewPicker.select to file succeed and uris are:' + uris);
      if (uris.length === 0) {
        resultHandler(undefined, null);
        return
      }
      const uri = uris[0];
      const fileName = new Uri.URI(uri).getLastSegment();
      const dstPath = `${saveDir}/${fileName}`;
      PhotoAccessPicker.readFromUriToPath(uri, dstPath)
        .then(() => {
          resultHandler(undefined, fileName);
        })
        .catch((err: BusinessError) => {
          resultHandler(err, undefined)
        })
    }).catch((err: BusinessError) => {
      // console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
      resultHandler(err, undefined);
    })
  }

  /**
   * 需保证此uri已存在
   * @param uri
   */
  private static async readFromUriToPath(uri: string, toPath: string) {
    destPath= toPath;
    let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
    predicates.equalTo(photoAccessHelper.PhotoKeys.URI, uri.toString());
    let fetchOptions: photoAccessHelper.FetchOptions = {
      fetchColumns: [photoAccessHelper.PhotoKeys.TITLE],
      predicates: predicates
    };

    try {
      let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOptions);
      let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
      console.info('getAssets photoAsset.uri : ' + photoAsset.uri);
      // 获取属性值,以标题为例;对于非默认查询的属性,get前需要在fetchColumns中添加对应列名
      console.info('title : ' + photoAsset.get(photoAccessHelper.PhotoKeys.TITLE));
      // 请求图片资源数据
      let requestOptions: photoAccessHelper.RequestOptions = {
        deliveryMode: photoAccessHelper.DeliveryMode.HIGH_QUALITY_MODE,
      }
      const a = await photoAccessHelper.MediaAssetManager.requestImageData(context, photoAsset, requestOptions, new MediaDataHandler());
      console.info('requestImageData successfully');
      fetchResult.close();
    } catch (err) {
      console.error('getAssets failed with err: ' + err);
    }
  }
}

在MediaAssetDataHandler中未能正确赋值,说明MediaAssetDataHandler不支持这种方式赋值啊,目前用全局的。