HarmonyOS 鸿蒙Next 扫描控件得到扫描沙箱结果后,保存到相册失败

发布于 1周前 作者 htzhanglong 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 扫描控件得到扫描沙箱结果后,保存到相册失败

用权限的办法好像不行,然后根据官网建议用phAccessHelper.showAssetsCreationDialog好像也不行,是哪里出问题了吗?卡在phAccessHelper.showAssetsCreationDialog这一步没有任何反应,也不往下执行,也没有任何提示,也没有进到catch,模拟器运行的

import { DocType, DocumentScanner, DocumentScannerConfig, SaveOption, FilterId, ShootingMode } from "@kit.VisionKit";
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { promptAction } from '@kit.ArkUI';
import { fileIo, fileUri } from '@kit.CoreFileKit';

@Entry
@Component
struct Index {
  async example(uri: string) {

    let context = getContext();
    let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
    try {
      // 指定待保存到媒体库的位于应用沙箱的图片uri
      let srcFileUri = uri;
      let srcFileUris: Array<string> = [
        srcFileUri
      ];
      // 指定待保存照片的创建选项,包括文件后缀和照片类型,标题和照片子类型可选
      let photoCreationConfigs: Array<photoAccessHelper.PhotoCreationConfig> = [
        {
          title: 'test', // 可选
          fileNameExtension: 'jpg',
          photoType: photoAccessHelper.PhotoType.IMAGE,
          subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选
        }
      ];
      // 基于弹窗授权的方式获取媒体库的目标uri
      let desFileUris: Array<string> = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
      // 将来源于应用沙箱的照片内容写入媒体库的目标uri
      let desFile: fileIo.File = await fileIo.open(desFileUris[0], fileIo.OpenMode.WRITE_ONLY);
      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);
      console.info('create asset by dialog successfully');
    } catch (err) {
      console.log('aaa' + err.message)
      console.error(`failed to create asset by dialog successfully errCode is: ${err.code}, ${err.message}`);
    }
  }

  build() {
    Column() {

      DocumentScanner({
        scannerConfig: {
          maxShotCount: 1,
          supportType: [DocType.DOC, DocType.SHEET],
          isGallerySupported: true
        },
        onResult: (code: number, saveType: SaveOption, uris: string[]) => {
          
          this.example(uris[0])
        }
      })
    }
    .width('100%')
    .height('100%')
  }
}

更多关于HarmonyOS 鸿蒙Next 扫描控件得到扫描沙箱结果后,保存到相册失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

1、是有报错的failed to create asset by dialog successfully errCode is 400001系统错误。

2、不能用模拟器去使用DocumentScanner

3、扫描后返回白屏是因为你的代码只有一个DocumentScanner,主界面没有任何组件。

4、DocumentScanner返回的uri不是沙箱路径,不能直接调showAssetsCreationDialog来存放到相册,所以需要先将其copy到沙箱,然后再去调showAssetsCreationDialog即可保存到相册。

demo:

import { DocType, DocumentScanner, DocumentScannerConfig, SaveOption, FilterId, ShootingMode } from "@kit.VisionKit";
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo as fs, fileUri, ReadOptions, WriteOptions } from '@kit.CoreFileKit';
import json from '@ohos.util.json';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct Index {
  filePath: string = '';

  async syncToSysAlbum(fileType: photoAccessHelper.PhotoType, extension: string, ...filePath: string[]) {
    let context = getContext(this);
    let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
    try {
      const srcFileUris: string[] = []
      filePath.forEach(path => {
        srcFileUris.push(path)
      })
      const config: photoAccessHelper.PhotoCreationConfig[] = []
      config.push({
        title: 'background', // 可选
        fileNameExtension: extension,
        photoType: fileType,
        subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选
      })
      console.log("syncToSysAlarm fileUri:" + json.stringify(srcFileUris) + ",config:" + json.stringify(config))
      const desFileUris = await phAccessHelper.showAssetsCreationDialog(srcFileUris, config)
      console.debug(`目标图片 uri is : ${JSON.stringify(desFileUris)}`)
      if (desFileUris.length > 0) {
        for (let index = 0; index < desFileUris.length; index++) {
          this.copyFileContentTo(srcFileUris[index], desFileUris[index])
        }
      }
    } catch (err) {
      console.log("syncToSysAlarm filePath:" + filePath + ",error:" + json.stringify(err))
    }
  }

  @State docImageUris: string[] = []

  build() {
    Stack({ alignContent: Alignment.Top }) {
      List() {
        ForEach(this.docImageUris, (uri: string) => {
          ListItem() {
            Image(uri)
              .objectFit(ImageFit.Contain)
              .width(100)
              .height(100)
          }
        })
      }
      .listDirection(Axis.Vertical)
      .alignListItem(ListItemAlign.Center)
      .margin({
        top: 50
      })
      .width('80%')
      .height('80%')

      DocumentScanner({
        scannerConfig: {
          maxShotCount: 1,
          supportType: [DocType.DOC, DocType.SHEET],
          isGallerySupported: true
        },
        onResult: (code: number, saveType: SaveOption, uris: string[]) => {
          this.docImageUris = uris
        }
      })
      Column() {
         Button("save")
           .onClick(()=>{
             for (let i = 0; i < this.docImageUris.length; i++) {
               console.info("testaaa in the sand: " + this.docImageUris[i])
               this.copyFileToSandBox(this.docImageUris[i])
             }
             this.syncToSysAlbum(photoAccessHelper.PhotoType.IMAGE,'png', this.filePath)
           })
      }
    }
    .width('100%')
    .height('100%')
  }

  copyFileToSandBox(strUri: string) {
    console.log("testaaa 开发复制文件")
    let context = getContext(this) as common.UIAbilityContext;
    // 通过UIAbilityContext获取沙箱地址filesDir,以Stage模型为例
    let pathDir = context.filesDir;
    console.log("testaaa 沙箱文件目录路径:", pathDir)
    let dstPath = pathDir + "/" + Date.now().toString() + "_tmpimg.png";
    this.filePath = fileUri.getUriFromPath(dstPath)
    console.log("testaaa 沙箱文件URI" + this.filePath);
    fs.copy(strUri, this.filePath, (err: BusinessError) => {
      if (err) {
        console.error(`testaaa Failed to copy: ${JSON.stringify(err)}`);
        return;
      }
      console.info("testaaa Succeeded in copying. ");
    })
  }

  /**
   * 复制文件内容到目标文件
   * @param srcFilePath 源文件路径
   * @param destFilePath 目标文件路径
   */
  copyFileContentTo(srcFilePath: string, destFilePath: string) {
    let srcFile = fs.openSync(srcFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
    let destFile = fs.openSync(destFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
    // 读取源文件内容并写入至目的文件
    let bufSize = 4096;
    let readSize = 0;
    let buf = new ArrayBuffer(bufSize);
    let readOptions: ReadOptions = {
      offset: readSize,
      length: bufSize
    };
    let readLen = fs.readSync(srcFile.fd, buf, readOptions);
    while (readLen > 0) {
      readSize += readLen;
      let writeOptions: WriteOptions = {
        length: readLen
      };
      fs.writeSync(destFile.fd, buf, writeOptions);
      readOptions.offset = readSize;
      readLen = fs.readSync(srcFile.fd, buf, readOptions);
    }
    // 关闭文件
    fs.closeSync(srcFile);
    fs.closeSync(destFile);
  }
}

更多关于HarmonyOS 鸿蒙Next 扫描控件得到扫描沙箱结果后,保存到相册失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


昨天已经解决了。
返回的uri不是沙箱路径,我用io流往沙箱写入再保存是可以的。
然后,模拟器可以用扫描控件。

针对帖子标题中提到的问题“HarmonyOS 鸿蒙Next 扫描控件得到扫描沙箱结果后,保存到相册失败”,可能的解决方案如下:

在HarmonyOS中,若扫描控件得到的扫描沙箱结果无法保存到相册,首先需确认应用是否具有写入相册的权限。在鸿蒙系统中,应用权限管理较为严格,需用户明确授权后,应用才能访问或修改特定数据。请检查应用权限设置,确保已授予“存储”或“相册”相关权限。

其次,检查保存图片的代码逻辑是否正确。鸿蒙系统提供了相应的API用于文件操作,需确保使用正确的API,并传入正确的路径和文件名。同时,注意检查沙箱结果数据是否完整,以及是否已正确转换为可保存的图片格式。

再者,考虑是否存在系统或硬件层面的限制。例如,设备存储空间不足、文件系统损坏等,均可能导致保存失败。可尝试在其他设备或模拟器上运行应用,以排除此类问题。

最后,查看系统日志或应用日志,分析是否有相关错误信息提示。根据错误信息,可进一步定位问题原因。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部