鸿蒙——获取系统相册 并举行图片上传

打印 上一主题 下一主题

主题 786|帖子 786|积分 2358

1.相机照相cameraPicker 流程:

1.打开相机后置摄像头得到照相结果集 cameraPicker.pick
const pickerResult = cameraPicker.pick( 配置参数)
2.根据结果集的URI属性同步打开文件 openSync
const file = fs.openSync(pickerResult.resultUri)
3.以同步方法获取文件详细属性信息 fs.statSync
const stat = fs.statSync(file.fd)
4.界说缓冲区用于生存读取的文件
const buffer = new ArrayBuffer(stat.size)
5.开始同步读取内容到缓冲区
fs.readSync(file.fd, buffer)
6.读取完毕后关闭文件流 close
fs.closeSync(file)
7.借助util工具方法把读取的文件流转成base64编码的字符串
util.Base64Helper( )
  1. import { camera, cameraPicker } from '@kit.CameraKit';
  2. import fs from '@ohos.file.fs';
  3. import { util } from '@kit.ArkTS';
  4. class CameraPlugin {
  5.    async pickerCamera(){
  6.       // 1. 打开相机后置摄像头得到拍照结果集
  7.       const pickerProfile: cameraPicker.PickerProfile = {
  8.          cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK
  9.       };
  10.       const pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(getContext(),
  11.          [cameraPicker.PickerMediaType.PHOTO], pickerProfile);
  12.       // 2. 根据结果集的URI属性同步打开文件
  13.       const file = fs.openSync(pickerResult.resultUri)
  14.       // 3. 同步读取文件的详情信息
  15.       const stat = fs.statSync(file.fd)
  16.       // 4. 定义缓冲区用于保存读取的文件
  17.       const buffer = new ArrayBuffer(stat.size)
  18.       // 5. 开始同步读取内容到缓冲区
  19.       fs.readSync(file.fd, buffer)
  20.       // 6. 读取完毕后关闭文件流
  21.       fs.closeSync(file)
  22.       // 7. 借助util工具方法把读取的文件流转成base64编码的字符串
  23.       const helper = new util.Base64Helper()
  24.       const str = helper.encodeToStringSync(new Uint8Array(buffer))
  25.       console.log('mk-logger', 'pickerCamera', str)
  26.       return str
  27.    }
  28. }
  29. export const cameraPlugin = new CameraPlugin()
复制代码
2.操作相册fs:


  • 打开相册选择图片 得到照相结果集 cameraPicker.pick
const photoSelectOptions = new picker.PhotoSelectOptions()
const photoPicker = new picker.PhotoViewPicker( );
const res = await photoPicker.select(photoSelectOptions)
——>获取照片的uri地址 const uri = res.photoUris[0]
      2.1根据结果集的URI属性同步打开文件 openSync
     const file = fs.openSync(uri)
    // 2.2 根据uri同步打开文件
    const file = fs.openSync(uri)
    // 2.3 同步获取文件的详细信息
    const stat = fs.statSync(file.fd)
    // 2.4 创建缓冲区存储读取的文件流
    const buffer = new ArrayBuffer(stat.size)
    // 2.5 开始同步读取文件流到缓冲区
    fs.readSync(file.fd, buffer)
    // 2.6 关闭文件流
    fs.closeSync(file)
    // 3. 转成base64编码的字符串
    const helper = new util.Base64Helper()
    const str = helper.encodeToStringSync(new Uint8Array(buffer))
  1. import { picker } from '@kit.CoreFileKit'
  2. import fs from '@ohos.file.fs';
  3. import { util } from '@kit.ArkTS';
  4. class PhotoPlugin {
  5.   async pickerPhoto(){
  6.      // 1. 打开相册选择图片
  7.      const photoSelectOptions = new picker.PhotoSelectOptions()
  8.          photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
  9.          photoSelectOptions.maxSelectNumber = 1;
  10.      const  photoPicker = new picker.PhotoViewPicker();
  11.      const res = await photoPicker.select(photoSelectOptions)
  12.      console.log('mk-logger', 'photoPlugin', JSON.stringify(res))
  13.     // 2. 文件操作
  14.     // 2.1 获取照片的uri地址
  15.     const uri = res.photoUris[0]
  16.     // 2.2 根据uri同步打开文件
  17.     const file = fs.openSync(uri)
  18.     // 2.3 同步获取文件的详细信息
  19.     const stat = fs.statSync(file.fd)
  20.     // 2.4 创建缓冲区存储读取的文件流
  21.     const buffer = new ArrayBuffer(stat.size)
  22.     // 2.5 开始同步读取文件流到缓冲区
  23.     fs.readSync(file.fd, buffer)
  24.     // 2.6 关闭文件流
  25.     fs.closeSync(file)
  26.     // 3. 转成base64编码的字符串
  27.     const helper = new util.Base64Helper()
  28.     const str = helper.encodeToStringSync(new Uint8Array(buffer))
  29.     console.log('mk-logger', 'photoPlugin-str', str)
  30.     return str
  31.    }
  32. }
  33. export const photoPlugin = new PhotoPlugin()
复制代码
3.获取系统相册 并举行图片上传:

picker选择系统相册图片,获取路径——>利用request.uploadFile方法完成应用步调缓存目录下的文件上传操作

        1.怎么获取的系统相册?( //picker选择系统相册图片,获取路径)

        我们这个项目内里有一个功能是上传头像,先利用picker这个API实现从系统上获取相册图片这个点的,起首要实例一个选择参数PhotoSelectOptions 内里必要设置媒体文件类型还有一个数目,然后—>实例一个选择器PhotoViewPicker,通过自带的——>select方法传入先前设置的选择参数即可完成选择。
        因为要上传嘛,所以我们通过上下文获取了一下应用缓存文件夹,然后利用fs.copyFileSync这个方法把图片拷贝到应用缓存文件夹内里。
——>把读取的文件生存到缓冲区buffer内里
const buffer = new ArrayBuffer(stat.size)
——>通过网络请求将Buffer中的数据上传到服务器。读取内容到缓冲区
fs.readSync(file.fd, buffer)
——>借助util工具方法把服务器读取的文件流(从二进制数据)转成base64编码的字符串
util.Base64Helper( )
        2.项目中图片上传是怎么做的?(利用request.uploadFile方法完成应用步调缓存目录下的文件上传操作)

        文件上传重要借助于鸿蒙request这个原生api的 uploadFile方法。
        但是这个方法不能直接读取相册中的内容,所以我们中间要做一个转换,用我们的fs和pick这两个api把我们相册的图片拷贝到了应用步调中来了。
        它必要传入两个参数,一个是当前应用的上下文(通过上下文,我们可以获取到拷贝到应用步调沙箱内里的文件的),一个是上传文件的配置参数,好比:吸收文件的后端接口,文件路径设置等,还有在header内里要设置Content-Type为multipart/form-data,表现当前上传的是一个多部分表单数据,这是做上传时必须要设置的,后端会根据这个类型去做文件的吸收处理惩罚。
  1. 'Content-Type': 'multipart/form-data'
复制代码
        3.request还有两个事件可以被我们监听,分别是progress 和 fail

        其中progress事件会返回上传文件的总巨细totalSize 和当前上传的巨细uploadSize,我们可以用来做上传进度的盘算和展示,uploadSize === totalSize 表现上传完成
        当时遇到一个题目,就是CustomDialogController弹窗是不会因为调用方的状态属性值改变而改变的,厥后通过研究利用emitter这个api来做的跨线程通信解决的。
        如果上传有错误,可以在fail的监听事件中来获取错误信息

有两个必要特殊注意的地方是:


  • 我们从系统相册中选择一个文件是没有权限读取的,必要利用上下文对象以及fs这个api将相册的文件拷贝到应用沙箱中,然后通过 internal://cache/再加上沙箱中的文件名才气正常做上传操作
  • 必要再你的应用中开启intelnet访问权限
图片上传封装:

  1. import { promptAction } from '@kit.ArkUI'
  2. import { iLoginDataModel } from '../models/AccountModel'
  3. import picker from '@ohos.file.picker';
  4. import fs from '@ohos.file.fs';
  5. import request from '@ohos.request';
  6. import { Logger } from '../common/utils/Logger';
  7. @Entry
  8. @Component
  9. struct ProfileEditPage {
  10.   @StorageLink('user') currentUser: iLoginDataModel = {} as iLoginDataModel
  11.   @StorageProp('topHeight') topHeight: number = 0
  12.   // 1.选择系统相册图片,获取路径(picker):
  13.   async pickerAvatar() {
  14.     //  1.1 实例化选择参数对象:
  15.     const options = new picker.PhotoSelectOptions()
  16.     options.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE // 表示从相册中选择图片
  17.     options.maxSelectNumber = 1 // 表示只选择一张
  18.     //   1.2 实例化选择器对象:
  19.     const pickerView = new picker.PhotoViewPicker()
  20.     //   1.3 调用选择器对象上的 select 方法传入参数对象即可完成选择
  21.     let res = await pickerView.select(options)
  22.     // AlertDialog.show({ message: JSON.stringify(res.photoUris) })
  23.     //   1.4 判断用户取消了选择图片,则组织下面代码的继续运行
  24.     if (res.photoUris.length === 0) {
  25.       promptAction.showToast({ message: "用户取消图片选择" })
  26.       return
  27.     }
  28.     //   1.5 准备好一个图片的完整路径:
  29.     let ext = 'jpg' // 图片扩展名
  30.     let fileName = Date.now().toString() // 图片名称
  31.     let cacheDir = getContext().cacheDir // 获取应用程序的缓存目录
  32.     let fullPath = cacheDir + '/' + fileName + '.' + ext // 完整的图片路径
  33.     let fullFileName = fileName + '.' + ext
  34.    
  35.     //   1.6 通过上面获取的文件路径 利用 fs.openSync 打开图片文件
  36.        ——> fs.copyFileSync将图片拷贝到缓存目录:
  37.     let file = fs.openSync(res.photoUris[0], fs.OpenMode.READ_ONLY)
  38.     fs.copyFileSync(file.fd, fullPath)
  39.     AlertDialog.show({ message: '图片拷贝成功' })
  40.     //  2.利用request.uploadFile方法完成应用程序缓存目录下的文件上传操作
  41.     //   2.1 通过上面的 fullFileName 获取缓存文件路径:
  42.     let uploadFilePath = `internal://cache/${fullFileName}`
  43.     //   2.2 准备reqeust.uploadFile :
  44.     //需要传入两个参数:上下文 + 上传文件的配置参数
  45.     let uploador = await request.uploadFile(getContext(), {
  46.       method: 'POST',
  47.       url: 'https://api-harmony-teach.itheima.net/hm/userInfo/avatar',
  48.       header: {
  49.         "Content-Type": "multipart/form-data",
  50.         "Authorization": `Bearer ${this.currentUser.token}`
  51.       },
  52.       files: [{ name: 'file', uri: uploadFilePath, filename: fullFileName, type: ext }],
  53.       // name:指的是接口中的body中的参数名称,不能写错一定要和接口保持一致
  54.       // uri:指的是应用程序缓存中的图片 //filename:文件名称
  55.       // type:文件类型,也就是扩展名
  56.       data: []  // 因为本接口除了上传文件之外,无需接收其他文本数据,所以空着即可
  57.     })
  58. //3.注册uploador对象上的两个事件:一个progress监听上传进度,一个fail监听上传失败的异常获取
  59.     uploador.on('progress', (uploadSize, totalSize) => {
  60. //这个回调函数是随着文件的上传会被不间断的触发执行,每次的uploadSize的值会增加
  61. //但是totalSize永远都是当前上传图片的大小
  62. //可以通过判断 uploadSize === totalSize 表示上传完成,我们就可以做完成后端逻辑处理
  63.       Logger.info('上传:',uploadSize + ' / '+ totalSize)
  64.       if(uploadSize === totalSize){
  65.         AlertDialog.show({message:'图片上传完成'})
  66.       }
  67.     //   由于此函数会被多次调用,所以我们可以在这个函数中计算处当前上传的进度百分比
  68.       // Logger.info('上传:', uploadSize + ' / ' + totalSize)
  69.       let parcentStr = ((uploadSize / totalSize) * 100).toFixed(0).toString()
  70.       Logger.info('上传:', parcentStr)
  71.     })
  72.   //  监听上传失败的事件
  73.     uploador.on('fail',(err)=>{
  74.       AlertDialog.show({message:JSON.stringify(err)})
  75.     })
  76.   }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万万哇

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表