张家二少
张家二少
  • 发布:2025-04-03 11:08
  • 更新:2025-09-01 16:52
  • 阅读:247

【报Bug】uniapp开发鸿蒙唤起前置相机拍照的时候,出现问题

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: 1

HBuilderX类型: 正式

HBuilderX版本号: 4.57

手机系统: Android

手机系统版本号: Android 14

手机厂商: OPPO

手机机型: PJV110

页面类型: nvue

vue版本: vue3

打包方式: 云端

项目创建方式: HBuilderX

示例代码:
// 调用鸿蒙摄像头插件  
export function openCamera(): Promise<string> {  
    console.log('####################################   调用成功')  
    return new Promise(async (resolve, reject) => {  
        try {  
            const pickerProfile : picker.PickerProfile = {  
                cameraPosition: camera.CameraPosition.CAMERA_POSITION_FRONT  
            };  
            const pickerResult : picker.PickerResult = await picker.pick(getContext(),  
                [picker.PickerMediaType.PHOTO], pickerProfile);  
            if (pickerResult.resultCode === 0) {  
                // 文件复制和读取逻辑  
                const file = fs.openSync(pickerResult.resultUri, fs.OpenMode.READ_ONLY)  
                const photoSize = fs.statSync(file.fd).size;  
                const buffer1 = new ArrayBuffer(photoSize);  
                fs.readSync(file.fd, buffer1);  
                const base64Str : string = buffer.from(buffer1).toString('base64')  
                resolve(base64Str);  
                console.log('####################################   调用成功', base64Str)  
                fs.closeSync(file);  
            } else {  
                console.error('Picker 调用失败,resultCode:', pickerResult.resultCode);  
                reject(new Error(`Picker 调用失败,resultCode: ${pickerResult.resultCode}`));  
            }  
        } catch (error) {  
            let err = error as BusinessError;  
            console.error('调用摄像头或读取文件时出错:', err);  
            reject(error);  
        }  
    });  
}  

操作步骤:
// 调用鸿蒙摄像头插件  
export function openCamera(): Promise<string> {  
    console.log('####################################   调用成功')  
    return new Promise(async (resolve, reject) => {  
        try {  
            const pickerProfile : picker.PickerProfile = {  
                cameraPosition: camera.CameraPosition.CAMERA_POSITION_FRONT  
            };  
            const pickerResult : picker.PickerResult = await picker.pick(getContext(),  
                [picker.PickerMediaType.PHOTO], pickerProfile);  
            if (pickerResult.resultCode === 0) {  
                // 文件复制和读取逻辑  
                const file = fs.openSync(pickerResult.resultUri, fs.OpenMode.READ_ONLY)  
                const photoSize = fs.statSync(file.fd).size;  
                const buffer1 = new ArrayBuffer(photoSize);  
                fs.readSync(file.fd, buffer1);  
                const base64Str : string = buffer.from(buffer1).toString('base64')  
                resolve(base64Str);  
                console.log('####################################   调用成功', base64Str)  
                fs.closeSync(file);  
            } else {  
                console.error('Picker 调用失败,resultCode:', pickerResult.resultCode);  
                reject(new Error(`Picker 调用失败,resultCode: ${pickerResult.resultCode}`));  
            }  
        } catch (error) {  
            let err = error as BusinessError;  
            console.error('调用摄像头或读取文件时出错:', err);  
            reject(error);  
        }  
    });  
}

预期结果:

预期的结果是,返回base64编码给nvue文件,那边调用接口

实际结果:

uts文件没有返回,经多次测试,图片过大,base64编码的数据太大了,传不过来

bug描述:

uniapp+vue3.0 ,适配鸿蒙的时候,需要做一个前置相机拍照的功能,因为后端要的是base64格式,我在uniapp的uni_module创建了uts文件,但是导致的问题是,无法转换base64,nvue文件一直拿不到base64格式的编码。 各位大佬都什么好的解决方案吗?在线等,很着急

2025-04-03 11:08 负责人:DCloud_UNI_OttoJi 分享
已邀请:
DCloud_UNI_OttoJi

DCloud_UNI_OttoJi - 日常回复 uni-app/x 问题,如果艾特我没看到,请主动私信

更新:

使用下面代码进行测试

import { cameraPicker as picker } from '@kit.CameraKit';  
import { camera } from '@kit.CameraKit';  
import { BusinessError } from '@kit.BasicServicesKit';  
import { buffer } from '@kit.ArkTS';  
import fs from '@ohos.file.fs';  

type IRes = {  
  base64Str : string  
  imageUri : string  
}  

export function openCamera() : Promise<IRes> {  
  return new Promise(async (resolve, reject) => {  
    try {  
      const pickerProfile : picker.PickerProfile = {  
        cameraPosition: camera.CameraPosition.CAMERA_POSITION_FRONT  
      };  
      const pickerResult : picker.PickerResult = await picker.pick(getContext(),  
        [picker.PickerMediaType.PHOTO], pickerProfile);  
      let imageUri = pickerResult.resultUri;  
      console.log('imageUri', imageUri)  
      // imageUri file://media/Photo/132/IMG_1756715765_097/IMG_20250901_163425.jpg  

      if (pickerResult.resultCode === 0) {  
        // 文件复制和读取逻辑    
        const file = fs.openSync(pickerResult.resultUri, fs.OpenMode.READ_ONLY)  
        const photoSize = fs.statSync(file.fd).size;  
        const buffer1 = new ArrayBuffer(photoSize);  
        fs.readSync(file.fd, buffer1);  
        const base64Str : string = buffer.from(buffer1).toString('base64')  
        console.log('####################################   调用成功', base64Str.length)  
        fs.closeSync(file);  

        const res : IRes = {  
          imageUri, base64Str  
        }  

        resolve(res);  
      } else {  
        console.error('Picker 调用失败,resultCode:', pickerResult.resultCode);  
        reject(new Error(`Picker 调用失败,resultCode: ${pickerResult.resultCode}`));  
      }  
    } catch (error) {  
      let err = error as BusinessError;  
      console.error('调用摄像头或读取文件时出错:', err);  
      reject(error);  
    }  
  });  
}

页面中使用

<template>  
  <view>  

    <image v-if="imageSrc" :src="imageSrc"></image>  
    <button @click="take1">take</button>  
  </view>  
</template>  

<script setup>  
  import {ref} from 'vue'  
  import {  
    openCamera  
  } from '@/uni_modules/otto-camera'  

  const imageSrc = ref('')  
  const take1 = async () => {  
    const res = await openCamera()  
    console.log(11, res.base64Str.length)  

    imageSrc.value = res.imageUri  

  }  

  const getExt = () => {  
    uni.getExtConfig({  
      success(data) {  
        console.log(data)  

      }  
    })  
  }  
</script>

打印这个值数据量比较大导致看不到,实际上打印返回值 url 和 str 的长度是正常的,截取前 1w 字符是正常的,通过 log 是看不到的,数据量比较大


如之前沟通,目前发现返回的字符串数据量比较大,初步测试有 600w 的长度,无法正确返回。

目前返回的 arraybuffer 看起来有问题,导致不能正确转成 base64。

可以看到返回临时文件的 url 可以进行 upload

目前会跟进此问题。

  • DCloud_UNI_OttoJi

    我更新了这个 demo,目前发现只是打印不出来,实际上字符串是存在的,截取前 1w 的字符,打印字符长度,通过 api 把字符串上传到服务端,功能都是正常的,目前此问题比较为不是 bug,后续会和鸿蒙做同步,是否是边缘情况导致无法数据回显。

    2025-09-01 17:08

要回复问题请先登录注册