鸿蒙应用开发-图片上传

429 阅读3分钟

图片上传

由于鸿蒙系统的隐私安全保护,应用无法直接从系统相册中获取到图片,所以鸿蒙系统的图片上传流程主要有以下几步:

  1. 通过鸿蒙官方的API唤起系统相册,让用户将需要上传的图片选中并返回其在内存中的临时路径
  2. 通过临时路径我们将图片拷贝到应用的沙箱中
  3. 通过上传文件的API将应用沙箱中的图片文件进行上传

主要API有以下几个

@ohos.file.photoAccessHelper (相册管理模块)

@ohos.file.fs (文件管理)

@ohos.request (上传下载)

步骤:

1.创建PhotoViewPicker实例

let photoPicker = new photoAccessHelper.PhotoViewPicker();

2.使用PhotoViewPicker的Select()方法获取图片路径

 const result = await photoPicker.select({
      //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。
      MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
      //选择媒体文件的最大数量
      maxSelectNumber: this.maxNumber
    })
AlertDialog.show( { message: JSON.stringify(result.photoUris) } )

下面是select()方法的参数信息,我们这里只使用了前两个,其他参数可以去文档中查看

BaseSelectOptions12+

图库选择选项基类。

名称类型必填说明
MIMEType10+PhotoViewMIMETypes可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。元服务API:  从API version 11开始,该接口支持在元服务中使用。
maxSelectNumber10+number选择媒体文件数量的最大值(最大可设置的值为500,若不设置则默认为50)。元服务API:  从API version 11开始,该接口支持在元服务中使用。

3.处理selec()方法的返回值

select()方法的返回值是一个字符串类型的数组,其中的每一项表示一个图片在内存的临时地址,使用一个数组进行接收存储

interface ImageList {
  /** 图片url */
  url: string;
}

imgList: ImageList[] = []
 if (result.photoUris?.length) {
      this.imgList = result.photoUris.map(url => {
        return { url } as ImageList
    })
 }

4.将图片拷贝到应用沙箱中

export const UpLoadFile = (list: ImageList[]): Promise<ImageList[]> => {
  // 1.获取当前应用文件路径
  const saveDir = getContext().cacheDir // cache目录
  // 创建一个存储每张图片文件参数的数组
  let fileParams: Array<request.File> = []
  // 循环遍历图片列表,为每张图片生成文件参数信息,并存储到数组中
  list.forEach(item => {
    // 生成一个唯一的名字,util.generateRandomUUID() 是一个用于生成随机 UUID (Universally Unique Identifier) 的函数。
    // UUID 是一种 128 位的数字,通常用于唯一标识信息。
    let filename = util.generateRandomUUID() + ".jpg"
    // item.url 相册路径  => 拷贝到cache目录下
    const file = fs.openSync(item.url, fs.OpenMode.READ_ONLY)
    fs.copyFileSync(file.fd, saveDir + "/" + filename)
    // 生成一个参数
    fileParams.push({
      filename,
      name: 'file',
      type: 'jpg',
      uri: `internal://cache/${filename}`
    })
    fs.closeSync(file.fd)
  })
  // 得到了参数,完成了拷贝
  //AlertDialog.show({ message: JSON.stringify(fileParams) })
  return uploadAPI(getContext(), fileParams)
}

5.通过request这个API的uploadFile()方法进行文件上传

export const uploadAPI = async (context: Context, files: request.File[]) => {
  return new Promise<ImageList[]>(async (resolve, reject) => {
    try {
      let arr: ImageList[] = []
      const task = await request.uploadFile(context, {
        url: '你需要上传的服务器接口地址',
        method: 'POST',
        header: {
        //根据要求填入请求头参数
          "Content-Type": "multipart/form-data",
           // 'Authorization': ''
        },
        files,
        data: []
      })
      task.on('progress', (uploadedSize, totalSize) => {
        console.log("upload_progress_:" + uploadedSize + ":" + totalSize)
      })
      task.on('fail', (event) => {
        reject(new Error("上传失败"))
        AlertDialog.show({ message: '失败:' + JSON.stringify(event) })
      })
      // 每次有响应结构都进来
      task.on("headerReceive", (header) => {
        if (header["body"]) {
          // 从响应头中的body对象中取到图片在服务器中的地址,存储到arr数组中
          const result = JSON.parse(header["body"]) as iResponse<string>
          arr.push({
            url: result.data!
          })
        }
      })
      task.on("complete", (event) => {
        // 彻底成功后,将存储图片在服务器中的地址的arr数组作为promise的成功结果(resolve)返回
        resolve(arr)
        //AlertDialog.show({ message: '成功:' + JSON.stringify(event) })
      })
    } catch (error) {
      promptAction.showToast({ message: error.message })
    }
  })
}