HarmonyOS 媒体文件 C++ 访问的问题

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/select-user-file-V5

如何用标准 C++ 库访问媒体文件?参考这个文档,获取到的本地路径传给 C++ 层,访问不到

HarmonyOS
2024-12-19 16:23:14
浏览
收藏 0
回答 1
回答 1
按赞同
/
按时间
fox280
#include "napi/native_api.h"
#include <xxxtream>
#include <string>
#include "hilog/log.h"
#include <sys/stat.h>
#include <unistd.h>
  bool isFileExists(const std::string &filename) {
  return access(filename.c_str(), F_OK) == 0;
}

std::string stringFromValue(napi_env env, napi_value value) {
  size_t length = 0;
  napi_get_value_string_utf8(env, value, nullptr, 0, &length);
  std::string ret_str(length, '\0');
  napi_get_value_string_utf8(env, value, (char *)ret_str.data(), length + 1, &length);
  return ret_str;
}

static napi_value Add(napi_env env, napi_callback_info info) {
  size_t requireArgc = 2;
  size_t argc = 2;
  napi_value args[2] = {nullptr};

  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

  napi_valuetype valuetype0;
  napi_typeof(env, args[0], &valuetype0);

  napi_valuetype valuetype1;
  napi_typeof(env, args[1], &valuetype1);

  double value0;
  napi_get_value_double(env, args[0], &value0);

  double value1;
  napi_get_value_double(env, args[1], &value1);

  napi_value sum;
  napi_create_double(env, value0 + value1, &sum);

  return sum;
}

static napi_value NAPI_Global_sendImageMessage(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

std::string localPath = stringFromValue(env, args[0]);
int fd;
napi_get_value_int32(env, args[1], &fd);
struct stat statdata;
int state = fstat(fd, &statdata);
OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "%{public}d %{public}d",fd,state);
OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "%{public}d",statdata.st_size);
}

static napi_value NAPI_Global_sendSandboxImage(napi_env env, napi_callback_info info) {
  size_t argc = 1;
  napi_value args[1] = {nullptr};
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

  std::string localPath = stringFromValue(env, args[0]);
  if (isFileExists(localPath)) {
    OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "NAPI_Global_sendSandboxImage exist");
  } else {
    OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "NAPI_Global_sendSandboxImage not exist");
  }
}
static napi_value NAPI_Global_sendSandboxFile(napi_env env, napi_callback_info info) {
  size_t argc = 1;
  napi_value args[1] = {nullptr};
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

  std::string localPath = stringFromValue(env, args[0]);
  if (isFileExists(localPath)) {
    OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "NAPI_Global_sendSandboxFile exist");
  } else {
    OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "NAPI_Global_sendSandboxFile not exist");
  }
}
static napi_value NAPI_Global_sendFileMessage(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

std::string localPath = stringFromValue(env, args[0]);
int fd;
napi_get_value_int32(env, args[1], &fd);
struct stat statdata;
int state = fstat(fd, &statdata);
OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "%{public}d %{public}d",fd,state);
OH_LOG_Print(LOG_APP, LOG_INFO, 1, "IM-Native", "%{public}d",statdata.st_size);
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
  napi_property_descriptor desc[] = {
    {"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},
  {"sendSandboxImage", nullptr, NAPI_Global_sendSandboxImage, nullptr, nullptr, nullptr, napi_default, nullptr},
  {"sendImageMessage", nullptr, NAPI_Global_sendImageMessage, nullptr, nullptr, nullptr, napi_default, nullptr},
  {"sendSandboxFile", nullptr, NAPI_Global_sendSandboxFile, nullptr, nullptr, nullptr, napi_default, nullptr},
  {"sendFileMessage", nullptr, NAPI_Global_sendFileMessage, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END

static napi_module demoModule = {
  .nm_version = 1,
  .nm_flags = 0,
  .nm_filename = nullptr,
  .nm_register_func = Init,
  .nm_modname = "entry",
  .nm_priv = ((void *)0),
  .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
export const add: (a: number, b: number) => number;

export const sendSandboxImage: (localPath: string) => void;

export const sendImageMessage: (localPath: string, fd: number) => void;

export const sendSandboxFile: (localPath: string) => void;

export const sendFileMessage: (localPath: string, fd: number) => void;
import testNapi from 'libentry.so';
import picker from '@ohos.file.picker';
import { BusinessError } from '@ohos.base';
import { FileUtil } from '../util/FileUtil';
import fileUri from "@ohos.file.fileuri";
import hilog from '@ohos.hilog';
import fs from '@ohos.file.fs';
import environment from '@ohos.file.environment';
@Entry
@Component
struct Index {
  @State message: string = '选择图片';

  aboutToAppear(): void {
    FileUtil.createFile(getContext(this));
    FileUtil.createImage(getContext(this));
  }

  build() {
    Row() {
      Column() {
        Button("发送沙盒图片").fontSize(25).fontWeight(FontWeight.Bold).onClick(() => {
          this.sendSandboxImage();
        })

        Button("选择相册图片并发送").fontSize(25).fontWeight(FontWeight.Bold).onClick(() => {
          this.chooseImage();
        })


        Button("发送沙盒文件").fontSize(25).fontWeight(FontWeight.Bold).onClick(() => {
          this.sendSandboxFile();
        })

        Button("选择手机文件并发送").fontSize(25).fontWeight(FontWeight.Bold).onClick(() => {
          this.chooseFile();
        })
      }.width('100%')
    }.height('100%')
  }

  private sendSandboxImage() {
    let localPath = FileUtil.getImagePath(getContext(this));
    hilog.info(0x0000, 'IM-ArkTs', "sendSandboxImage " + localPath);
    testNapi.sendSandboxImage(localPath);
  }

  private chooseImage() {
    const photoSelectOptions = new picker.PhotoSelectOptions();
    photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
    photoSelectOptions.maxSelectNumber = 5; // 选择媒体文件的最大数目
    const photoViewPicker = new picker.PhotoViewPicker();
    photoViewPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => {
      let imageUris = photoSelectResult.photoUris;
      if (imageUris.length > 0) {
        let localPath = imageUris[0];
        hilog.info(0x0000, 'IM-ArkTs', "sendImageMessage " + localPath);
        // file://media/Photo/16/IMG_1718281435_015/IMG_20240613_202215.jpg
        let file = fs.openSync(localPath, fs.OpenMode.READ_ONLY);
        console.info('file fd: ' + file.fd);
        console.info('file fd: ' + file.path);
        console.info('file fd: ' + file.name);
        // /Photo/16/IMG_1718281435_015
        let file2 = fs.dup(file.fd);
        console.info("The name of the file2 is " + file2.name);
        console.info("The Path of the file2 is " + file2.path)
        hilog.info(0x0000, 'IM-ArkTs', "sendImageMessage " + localPath);
        testNapi.sendImageMessage(localPath, file.fd);
      }
    }).catch((err: BusinessError) => {
      console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
    })
  }

  private sendSandboxFile() {
    let localPath = FileUtil.getFilePath(getContext(this));
    //不能写这行代码,否则底层 C++ 访问不到该地址
    // /data/storage/el2/base/haps/entry/files/test.txt
    hilog.info(0x0000, 'IM-ArkTs', "sendSandboxFile " + localPath);
    testNapi.sendSandboxFile(localPath);
  }

  private chooseFile() {
    const documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.maxSelectNumber = 5; // 选择文档的最大数目(可选)
    documentSelectOptions.defaultFilePathUri = "file://docs/storage/Users/currentUser/test"; // 指定选择的文件或者目录路径(可选)
    documentSelectOptions.fileSuffixFilters = ['.png', '.txt', '.mp4']; // 选择文件的后缀类型,若选择项存在多个后缀名,则每一个后缀名之间用英文逗号进行分隔,而且后缀类型名不能超过100个(可选)。

    const documentViewPicker = new picker.DocumentViewPicker(); // 创建文件选择器实例
    documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      let uris = documentSelectResult;
      if (uris.length > 0) {
        let localPath = uris[0];
        hilog.info(0x0000, 'IM-ArkTs', "sendImageMessage " + localPath);
        // file://docs/storage/Users/currentUser/fm7.txt
        let file = fs.openSync(localPath, fs.OpenMode.READ_ONLY);
        console.info('file fd: ' + file.fd);
        console.info('file fd: ' + file.path);
        console.info('file fd: ' + file.name);
        // /storage/Users/currentUser/fm7.txt
        let file2 = fs.dup(file.fd)
        console.info("The name of the file2 is " + file2.fd);
        console.info("The name of the file2 is " + file2.name);
        console.info("The Path of the file2 is " + file2.path)
        hilog.info(0x0000, 'IM-ArkTs', "sendFileMessage " + file.path);
        testNapi.sendFileMessage(localPath,file.fd);
      }
    }).catch((err: BusinessError) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
    })
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
分享
微博
QQ
微信
回复
2024-12-19 18:57:24
相关问题
HarmonyOS 获取媒体文件失败13900012
1066浏览 • 1回复 待解决
HarmonyOS 获取媒体文件具体路径
958浏览 • 1回复 待解决
在读取媒体文件open: permission denied
3841浏览 • 1回复 待解决
ArkTS层通过接口访问C++层对象
1225浏览 • 1回复 待解决
使用C++进行HarmonyOS开发问题
2142浏览 • 2回复 待解决
HarmonyOS C++如何读取指定路径文件
702浏览 • 1回复 待解决
c/c++层主动调用ArkTS存在问题
1650浏览 • 1回复 待解决
HarmonyOS ArkTS与C/C++交互
1753浏览 • 1回复 待解决
基于HAR跨模块C++文件引用
1921浏览 • 1回复 待解决
如何修改C++版本?C++支持情况?
2202浏览 • 1回复 待解决
HarmonyOS 调用C++接扣将数据写入文件
562浏览 • 1回复 待解决
HarmonyOS媒体资源访问方式
884浏览 • 1回复 待解决