您的当前位置:首页正文

【鸿蒙】- HarmonyOS Next中实现图片上传

2024-11-11 来源:个人技术集锦

前言

在手机APP中,图片上传功能为用户提供了便捷的方式来分享和传递视觉信息。无论是在社交媒体上分享旅行照片、美食体验,还是在工作场合中提交项目进展报告、展示设计成果,用户都能通过图片上传功能轻松实现。这一功能的实现,不仅满足了用户对于信息分享和传递的需求,还使用户可以更加直观地表达自己的想法和感受,与他人进行更加丰富的交流。

实现步骤

选择相册图片

因为选择图片需要用到 picker,接下来让简单介绍一下Picker。

选择器(Picker)是一个封装PhotoViewPicker、DocumentViewPicker、AudioViewPicker等API模块,具有选择与保存的能力。应用可以自行选择使用哪种API实现文件选择和文件保存的功能。其中我们主要使用的是PhotoViewPicker。

PhotoViewPicker(图库选择器对象),用来支撑选择图片/视频和保存图片/视频等用户场景。

更多的详情请参考选择用户文件 (openharmony.cn)

具体的实现逻辑如下:

import picker from '@ohos.file.picker';

// 一、定义图片选择 Picker 的配置
// 实例化 选项对象
const photoSelectOptions = new picker.PhotoSelectOptions();
// 过滤选择媒体文件类型为IMAGE
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; 
// 选择媒体文件的最大数目
photoSelectOptions.maxSelectNumber = 1; 


// 二、创建 图片选择对象并选择图片
const photoViewPicker = new picker.PhotoViewPicker();
// 调用 select 方法,传入选项对象
 photoViewPicker.select(photoSelectOptions).then(res=>{
    const uri = res.photoUris[0]
    // 因为只选了一张
    AlertDialog.show({ message: '图片路径为:' + uri })
 })

拷贝图片到缓存目录

当前上传应用文件功能,不支持直接上传本地相册的文件,仅支持上传应用缓存文件路径(cacheDir)下的文件。

在使用上传功能前,需要先申请权限,即在module.json5配置文件的requestPermissionsrequestPermissions标签中声明权限。

 "requestPermissions":[
      {
        "name" : "ohos.permission.INTERNET",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when":"inuse"
        }
      }
 ]

更多的详情请参考@ohos.file.fs (文件管理) (openharmony.cn)

import fs from '@ohos.file.fs';

// 三.将文件保存到缓存目录(只能上传在缓存目录中的文件)
const context = getContext(this)
const fileType = 'jpg'
// 生成一个新的文件名
const fileName = Date.now() + '.' + fileType
// 通过缓存路径+文件名 拼接出完整的路径
const copyFilePath = context.cacheDir + '/' + fileName
// 将文件 拷贝到 临时目录
const file = fs.openSync(uri, fs.OpenMode.READ_ONLY)
fs.copyFileSync(file.fd, copyFilePath)

上传文件

准备好参数调用request.uploadFile()获得上传对象 uploader

给uploader对象注册progress事件,监听上传进度 requestRes.on("progress", (uploadedSize: number, totalSize: number)=>{})


import request from '@ohos.request';
import http from '@ohos.net.http';

  // 四、上传图片
  // 上传文件
  let files: Array<request.File> = [
  // internal://cache/ 固定的
    { filename: fileName, type: fileType, name: 'img', uri: `internal://cache/${fileName}` }
  ]

  request.uploadFile(context, {
    url: '接口地址', // url 地址
    method: 请求方法, // 请求方法
    header: {
      // 和接口文档的要求的格式对象
      contentType: '',
    },
    files, // 文件信息
    data: [] // 额外提交的数据,不能省略
  })
    .then((res => {
      //获取到响应的内容
      res.on('headerReceive', (value) => {
        // 根据接口文档 转为对应的类型即可
        const uploadRes = (value as UploadResponse)
        const response = JSON.parse(uploadRes.body) as Response
        AlertDialog.show({
          message: response.data.url
        })
        console.log('上传的地址为:', response.data.url)

      })
    }))

完整代码

import picker from '@ohos.file.picker';
import fs from '@ohos.file.fs';
import request from '@ohos.request';
import http from '@ohos.net.http';

// 定义类型
interface UploadResponse {
  body: string
}

export interface Response {
  /**
   * 业务状态码
   */
  code: number;

  /**
   * 响应数据
   */
  data: Data;

  /**
   * 响应消息
   */
  message: string;
}

/**
 * 响应数据
 */
export interface Data {
  /**
   * 上传成功的图片-在线地址
   */
  url: string;
}


// 实例化 选项对象
const photoSelectOptions = new picker.PhotoSelectOptions();
// 过滤选择媒体文件类型为IMAGE
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
// 选择媒体文件的最大数目
photoSelectOptions.maxSelectNumber = 1;

@Entry
@Component
struct Page03_uploadImg {
  
  @State img :string =''
  
  build() {
    Navigation() {

      Column() {

        Image(this.img)

        Button('选择并上传图片')
          .onClick(() => {
            // 创建 图片选择对象
            const photoViewPicker = new picker.PhotoViewPicker();
            // 调用 select 方法,传入选项对象
            photoViewPicker.select(photoSelectOptions)
              .then(res => {
                const uri = res.photoUris[0]
                // 因为只选了一张
                // AlertDialog.show({ message: '图片路径为:' + uri })

                // 三、拷贝文件到缓存目录
                // 将文件保存到缓存目录(只能上传在缓存目录中的文件)
                const context = getContext(this)
                const fileType = 'jpg'
                // 生成一个新的文件名
                const fileName = Date.now() + '.' + fileType
                // 通过缓存路径+文件名 拼接出完整的路径
                const copyFilePath = context.cacheDir + '/' + fileName

                // 将文件 拷贝到 临时目录
                const file = fs.openSync(uri, fs.OpenMode.READ_ONLY)
                fs.copyFileSync(file.fd, copyFilePath)

                // 四、上传图片
                // 上传文件
                let files: Array<request.File> = [
                // internal://cache/ 固定的
                // name 和接口文档的要求对上
                  { filename: fileName, type: fileType, name: 'img', uri: `internal://cache/${fileName}` }
                ]

                request.uploadFile(context, {
                  
                  url: '你的url 地址', // url 地址
                  
                  method: http.RequestMethod.POST, // 请求方法
                  header: {
                    // 和接口文档的要求的格式对象
                    contentType: 'multipart/form-data',
                  },
                  files, // 文件信息
                  data: [] // 额外提交的数据,不能省略
                })
                  .then((res => {
                    // 获取响应的内容
                    res.on('headerReceive', (value) => {
                      const uploadRes = (value as UploadResponse)
                      const response = JSON.parse(uploadRes.body) as Response
                      AlertDialog.show({
                        message: response.data.url
                      })
                      this.img = response.data.url
                    })
                  }))
              })
          })
      }
    }
    .titleMode(NavigationTitleMode.Mini)
    .title('上传图片')
  }
}
Top