Harmonyos Next——图片上传与下载

Harmonyos Next------图片上传与下载

图片上传至服务器

描述

从手机相册中选择一张图片,然后上传至服务器

选取图片

在从相册或者拍摄获取的图片之前,需要进行权限申请,其权限为媒体内容读写权限

'ohos.permission.READ_MEDIA' //允许应用读取用户外部存储中的媒体文件信息-用户授权

s'ohos.permission.WRITE_MEDIA' //允许应用读写用户外部存储中的媒体文件信息-用户授权

从相册选择图片

通过picker.PhotoViewPicker()选择相册内容,在选择之前可以设置选择数量、资源类型等。

例如选取其中一张图片,返回的URI格式如下:

file://media/Photo/2/IMG_1713776063_001/screenshot_20240422_165243.jpg

但此格式并不能直接上传至服务器,需要对其进行拷贝,格式转换等操作,将在下节进行阐述。

c 复制代码
  private async openGallery(onSuccess: (uri: string)=> void, onFailed: (error: string)=>void) {
    try {
      let PhotoSelectOptions = new picker.PhotoSelectOptions()
      PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE
      PhotoSelectOptions.maxSelectNumber = 1
      let photoPicker = new picker.PhotoViewPicker()
      photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: picker.PhotoSelectResult) => {
        //file://media/Photo/2/IMG_1713776063_001/screenshot_20240422_165243.jpg
        if (PhotoSelectResult.photoUris.length > 0) {
          onSuccess(PhotoSelectResult.photoUris[0])
        }
      }).catch((err: BusinessError) => {
        LoggerJoy.error('PhotoViewPicker.select failed with err: ' + JSON.stringify(err))
        onFailed(err.message)
      })
    } catch (error) {
      let err: BusinessError = error as BusinessError
      LoggerJoy.error('PhotoViewPicker failed with err: ' + JSON.stringify(err))
      onFailed(err.message)
    }
  }

通过拍摄获取图片

通过cameraPicker.pick打开相机页面,如果完成拍照并点击确认,则会返回如上节一样格式的URI

c 复制代码
  private async openCamera(onSuccess: (uri: string)=> void, onFailed: (error: string)=>void){
    try {
      let pickerProfile: cameraPicker.PickerProfile = {
        cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK
      }
      let pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(
        getContext(this),
        [cameraPicker.PickerMediaType.PHOTO, cameraPicker.PickerMediaType.VIDEO],
        pickerProfile
      )
      if (pickerResult) {
        onSuccess( pickerResult.resultUri)
      }
    } catch (error) {
      let err = error as BusinessError
      LoggerJoy.error(`the pick call failed. error code: ${err.code}`)
      onFailed(err.message)
    }
  }

将获取的图片上传至服务器

由于上述获取的文件为file开头,外部并不能直接进行访问,可以将其拷贝到APP目录下的沙箱文件中。由于本Demo采用的是系统提供的request.uploadFile,其路径前缀指定为internal://cache/,所有还需在拷贝之后的新路径前加上此前缀,此前缀对应的是临时目录cacheDir

拷贝文件

拷贝之后的文件存放于应用目录下的沙箱文件中

c 复制代码
  private async copyFileToCache(path: string, context: Context): Promise<string>{
    try {
      let file = await fs.open(path, fs.OpenMode.READ_WRITE)
      if (file){
        let dir =  context.cacheDir + '/avatar'
        if (!fs.accessSync(dir)) {
          fs.mkdirSync(dir)
        }
        let newpath = context.cacheDir + `/avatar/hohem${new Date().getTime()}.jpg`
        LoggerJoy.info(`newpath:${newpath}`)
        await fs.copyFile(file.fd, newpath)
        return newpath
      }
      return ''
    } catch (err){
      LoggerJoy.info("applog:open file failed with error message: " + err.message + ", error code: " + err.code)
      return ''
    }
  }

上传图片

在使用request前需要导入对应包

import { BusinessError, request } from '@kit.BasicServicesKit'

拷贝之后的路径格式如下

/data/storage/el2/base/haps/entry/cache/avatar/hohem1713924905931.jpg

然后在其前面添加指定前缀internal://cache/,由于此前缀对应的便是cacheDir目录,所以将拷贝之后的路径前面一部分进行省略,最终得到的路径如下

internal://cache/avatar/hohem1713924905931.jpg

若未对路径进行转换,会出现401-the parameters check fails this is fail path异常错误。

在进行上传时,需根据自己云服务器所配置的接受数据格式进行变化request.UploadConfig,例如是PUT还是POST,是否还需其他头参数,例如id、token等

c 复制代码
  private async uploadFileToCloud(context: Context, uploadUrl: string, path: string, avatar: string, onSuccess: (avatar: string)=> void, onFailed: (error: string) => void){
    let newPath = await this.copyFileToCache(path, context)//---/data/storage/el2/base/haps/entry/cache/avatar/hohem1713924905931.jpg
    newPath = `internal://cache/${newPath.split("cache/")[1]}` //internal://cache/avatar/hohem1713924905931.jpg
    LoggerJoy.info(`newpath:${newPath}`)
    let file: Array<request.File> = [
      {
        name: 'avatarName',
        filename: 'avatarFilename',
        uri: newPath,
        type: 'image'
      }
    ]

    let config: request.UploadConfig = {
      url: uploadUrl,
      method: 'PUT',
      files: file,
      header: {
        'Content-Type': 'application/octet-stream'
      },
      data: []
    }

    try {
      request.uploadFile(
        context,
        config
      ).then((result)=>{
        onSuccess(avatar)
      }).catch((err: BusinessError)=>{
        onFailed(err.message)
      })
    } catch (error) {
      //401-the parameters check fails   this is fail path
      onFailed((error as BusinessError).message)
    }
  }

图片下载

下载图片比上传图片简单的多,依旧使用系统提供的request.downloadFileAPI完成。

例如存在https://xxxxxxx.com/system/202403/1773228028463067136.jpgURL图片资源,

为了减少文件名称冗余和唯一性,我们可以只截取最后一部分做为下载之后的图片名称(1773228028463067136.jpg),然后同样保存到应用目录下的沙箱文件下。

最后调用request.downloadFile即可完成对应下载功能

c 复制代码
  private downloadImages(context: Context,url: string){
    let splits = url.split('/')
    let fileName = splits[splits.length - 1]
    let basePath = context.cacheDir + '/banner' //:/data/storage/el2/base/haps/entry/cache/banner/1773228028463067136.jpg
    this.checkBannerDirExist(basePath) //如果目录不存在,则直接创建目录
    let config: request.DownloadConfig = {
      url: url,
      filePath: `${basePath}/${fileName}`
    }
    try {
      request.downloadFile(context, config, (err: BusinessError, data: request.DownloadTask)=>{
        if (err) {
          //下载失败
          LoggerJoy.info(`write local banner failed:${url}`)
          return
        }
        LoggerJoy.info(`download banner successful:${url}`)
        //下载成功
      })
    } catch (error) {
      LoggerJoy.info(`write local banner failed:${(error as BusinessError).message}`)
    }
  }
相关推荐
以太浮标4 小时前
华为eNSP模拟器综合实验之-DHCP服务中继配置案例
网络·华为·智能路由器·信息与通信
游戏技术分享4 小时前
【鸿蒙游戏技术分享 第75期】AGC后台批量导入商品失败,提示“参数错误”
游戏·华为·harmonyos
No Silver Bullet4 小时前
HarmonyOS NEXT开发进阶(十七):WebView 拉起 H5 页面
华为·harmonyos
liuhaikang5 小时前
【鸿蒙HarmonyOS Next App实战开发】口语小搭档——应用技术实践
harmonyos
北方的流星6 小时前
华为交换机MSTP和VRRP综合应用配置
运维·网络·华为
C雨后彩虹8 小时前
简易内存池
java·数据结构·算法·华为·面试
liuhaikang8 小时前
鸿蒙VR视频播放库——md360player
音视频·vr·harmonyos
北方的流星10 小时前
华为交换机IPv6静态路由、默认路由、RIPng和OSPFv3路由配置
运维·网络·华为
飞露10 小时前
鸿蒙Preview预览文件失败原因
华为·harmonyos
夏小鱼的blog10 小时前
【HarmonyOS应用开发入门】第五期:状态管理V2入门 - 1
harmonyos·状态管理