摘要:在移动应用开发中,图片上传是一个极其常见的需求。本文将手把手教你如何在 HarmonyOS 应用中使用 DevEco Studio 和 ArkTS 语言,从相册选择图片并将其上传到指定的网络服务器。

一、环境准备与项目创建
  1. 1.安装 DevEco Studio:确保你已安装最新版本的 DevEco Studio,并配置好 HarmonyOS SDK。

  2. 2.创建新项目:打开 DevEco Studio,选择一个空的 Ability 模板(例如 Empty Ability),语言选择 ArkTS

二、核心功能实现步骤

我们将这个过程分解为三个核心步骤:

  1. 1.申请权限:访问用户相册需要权限。

  2. 2.选择图片:调用系统提供的图片选择器。

  3. 3.上传图片:将获取到的图片文件上传到服务器。


三、详细代码实现

第一步:配置权限和模型

module.json5 文件中,添加所需的网络权限和访问媒体文件的权限。

{
  "module": {
    ...
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      },
      {
        "name": "ohos.permission.READ_IMAGE",
        "reason": "$string:reason_desc", // 在string.json中配置原因描述
        "usedScene": {
          "abilities": [
            "MainAbility"
          ],
          "when": "always"
        }
      }
    ]
  }
}
​
​
​
​

第二步:构建UI界面 (Index.ets)

我们在页面上放置一个按钮用于触发选择图片,一个图片组件用于预览,另一个按钮用于触发上传,并提供一个文本区域显示上传结果。

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  // 保存选取的图片文件对象
  @State selectedFile: string = ''
  // 保存上传结果信息
  @State resultMessage: string = ''
​
  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(30)
          .fontWeight(FontWeight.Bold)
​
        // 预览图片
        if (this.selectedFile) {
          Image(this.selectedFile)
            .width(200)
            .height(200)
            .margin(15)
        }
​
        // 选择图片按钮
        Button('从相册选择图片')
          .width(200)
          .margin(15)
          .onClick(() => {
            this.pickImage()
          })
​
        // 上传图片按钮
        Button('上传图片')
          .width(200)
          .margin(15)
          .onClick(() => {
            this.uploadImage()
          })
​
        // 显示上传结果
        Text(this.resultMessage)
          .fontSize(16)
          .margin(15)
      }
      .width('100%')
    }
    .height('100%')
  }
  
  // 接下来将实现 pickImage 和 uploadImage 方法
}
​
​
​
​

第三步:实现选择图片方法 (pickImage)

Index 组件内添加方法,调用 @ohos.file.picker 模块来选择图片。

import picker from '@ohos.file.picker';
import { BusinessError } from '@ohos.base';
​
async pickImage() {
  try {
    let photoPicker = new picker.PhotoViewPicker();
    let photoSelectOptions = new picker.PhotoSelectOptions();
    photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤只显示图片
    photoSelectOptions.selectCount = 1; // 选择一张图片
​
    let photoSelectResult = await photoPicker.select(photoSelectOptions);
    if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
      // 将选中的图片URI赋值给selectedFile,用于预览
      this.selectedFile = photoSelectResult.photoUris[0];
      this.resultMessage = `图片选择成功: ${this.selectedFile}`;
    }
  } catch (err) {
    let error = err as BusinessError;
    this.resultMessage = `选择图片失败,错误码: ${error.code}, 错误信息: ${error.message}`;
  }
}
​
​
​
​

第四步:实现上传图片方法 (uploadImage)

Index 组件内添加方法,使用 @ohos.net.http 模块发起网络请求。这里以标准的 FormData 格式上传为例。

import http from '@ohos.net.http';
import fs from '@ohos.file.fs';
​
async uploadImage() {
  // 1. 检查是否已选择图片
  if (!this.selectedFile) {
    this.resultMessage = '请先选择一张图片!';
    return;
  }
​
  // 2. 创建 HTTP 请求
  let httpRequest = http.createHttp();
  let url = 'https://your-server.com/upload'; // 请替换为你自己的服务器上传地址
​
  // 3. 读取文件数据
  let file = fs.openSync(this.selectedFile, fs.OpenMode.READ_ONLY);
  let fileStat = fs.statSync(this.selectedFile);
  let fileData = new ArrayBuffer(fileStat.size);
  fs.readSync(file.fd, fileData);
  fs.closeSync(file);
​
  // 4. 构建请求表单数据
  let request = http.RequestData.createFromBytes(fileData);
  let formDataArray: http.FormData[] = [
    {
      name: 'file', // 字段名,需与服务器端对应
      value: request,
      filename: this.selectedFile.split('/').pop() // 取文件名
    },
    // 可以添加其他普通字段
    // { name: 'token', value: 'your_token_here' }
  ];
​
  // 5. 发起请求
  try {
    let response = await httpRequest.request(
      url,
      {
        method: http.RequestMethod.POST,
        header: {
          'Content-Type': 'multipart/form-data',
        },
        extraData: formDataArray
      }
    );
​
    // 6. 处理响应
    if (response.responseCode === 200) {
      this.resultMessage = `上传成功!服务器返回:${response.result}`;
    } else {
      this.resultMessage = `上传失败,状态码:${response.responseCode}`;
    }
  } catch (err) {
    let error = err as BusinessError;
    this.resultMessage = `网络请求失败,错误码: ${error.code}, 错误信息: ${error.message}`;
  } finally {
    // 7. 释放资源
    httpRequest.destroy();
  }
}
​
​
​
​

四、注意事项与优化建议
  1. 1.权限申请逻辑:上述代码省略了动态申请权限 (ohos.permission.READ_IMAGE) 的代码。在实际应用中,你需要在调用 pickImage 前使用 abilityAccessCtrl 模块检查并动态申请权限,以提供更好的用户体验。

  2. 2.服务器地址:将示例中的 https://your-server.com/upload 替换为你实际的后端接口地址。

  3. 3.错误处理:示例提供了基本的错误处理,在实际生产中可能需要更精细的错误分类和处理(如网络异常、服务器错误、文件过大等)。

  4. 4.性能优化:•压缩图片:上传前可先对图片进行适当压缩,减少流量消耗和提高上传速度。可使用 @ohos.image 模块。•多图上传:修改 selectCount 并循环处理 photoUris 数组即可支持多图上传。•进度显示http 模块支持 on 方法监听下载进度,可用于制作上传进度条。

  5. 5.安全:如果服务器需要鉴权,记得在请求头中添加 Authorization 等 token 字段。

五、总结

通过以上步骤,我们成功地在 HarmonyOS 应用中实现了:

  • •使用 PhotoViewPicker 选择系统相册图片。

  • •使用 http 模块以 multipart/form-data 格式将图片文件上传到服务器。

这个流程是移动端图片上传的通用解决方案。希望这篇博客能对你的开发工作有所帮助!你可以在 DevEco Studio 中亲自尝试,并根据自己的业务需求进行扩展和优化。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐