HarmonyOS 5.1.1版本图片上传功能

一、服务端实现(Spring Boot)

服务端采用Spring Boot框架接收图片上传请求,核心实现如下:

接口设计

  • 请求方式:POST
  • 内容类型:multipart/form-data
  • 接口路径:/updateAvatar
  • 文件参数名:file(与客户端保持一致)

核心代码

kotlin 复制代码
@PostMapping("updateAvatar")
fun updateAvatar(
    @RequestParam("file") file: MultipartFile?,
): GeneralResult<LoginResultVO> {
    return GeneralResult.success(userService.modifyUserAvatarUrl(file))
}

服务端通过@RequestParam("file")注解接收客户端上传的图片文件,类型为MultipartFile,然后调用业务层方法处理文件并返回结果。

二、鸿蒙客户端实现

鸿蒙客户端实现图片上传功能主要分为四个步骤:选择图片、读取文件、上传文件,全程无需申请文件访问权限,仅访问用户明确选择的文件。

1. 选择图片(PhotoViewPicker)

使用鸿蒙系统提供的photoAccessHelper.PhotoViewPicker组件实现图片选择,该组件无需额外权限申请,仅能访问用户明确选择的图片。

实现步骤:

初始化选择器

typescript 复制代码
// 初始化图片选择器
photoPicker = new photoAccessHelper.PhotoViewPicker();

// 配置选择参数
options: photoAccessHelper.PhotoSelectOptions = {
  maxSelectNumber: 1, // 限制最大选择数量为1张
  MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE // 仅允许选择图片类型
};

调用选择器并处理结果

typescript 复制代码
// 调用选择器
this.photoPicker.select(this.options)
  .then((result) => {
    let uriList = result.photoUris; // 获取选中图片的URI数组
    // 判断是否选择了图片
    if (ArrayUtil.isNotEmpty(uriList)) {
      this.viewModel.state.imageUri = uriList[0]; // 保存选中图片的URI
      this.viewModel.updateAvatar(); // 触发上传操作
    }
  })
  .catch((err: BusinessError) => {
    // 处理选择过程中的异常
    console.error("图片选择失败:" + err.message);
  });

2. 读取文件内容

选择图片后获得的是图片的URI,不能直接用于上传,需要通过文件IO操作读取文件内容到ArrayBuffer中。

typescript 复制代码
// 打开文件,以只读模式
let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY);

// 获取文件信息(包括文件大小)
let fileStat = fileIo.statSync(file.fd);

// 初始化与文件大小匹配的缓冲区
let arrayBuffer = new ArrayBuffer(fileStat.size);

// 将文件内容读取到缓冲区
let readLen = fileIo.readSync(file.fd, arrayBuffer);

// 验证读取长度是否与文件大小一致
if (readLen !== fileStat.size) {
  console.warn("文件读取不完整,实际读取:" + readLen + ",文件大小:" + fileStat.size);
}

// 关闭文件,释放资源
fileIo.closeSync(file);

// 从URI中提取文件名
const fileName = uri.substring(uri.lastIndexOf('/') + 1);

3. 上传文件(NetworkKit)

使用鸿蒙@kit.NetworkKit提供的HTTP能力实现文件上传,核心是配置multipart/form-data类型的请求。

封装上传方法
typescript 复制代码
static postFile<T>(url: string, fileData: ArrayBuffer, fileName: string): Promise<Result<T>> {
  // 创建HTTP请求对象
  let httpRequest = http.createHttp();
  
  return new Promise<Result<T>>((resolve) => {
    // 发起POST请求
    httpRequest.request(
      HttpService.BASE_URL + url,
      {
        method: http.RequestMethod.POST,
        header: {
          // 必须指定为multipart/form-data类型
          'Content-Type': 'multipart/form-data'
        },
        // 配置表单数据
        multiFormDataList: [ 
          {
            name: 'file',  // 与服务端定义的参数名保持一致
            contentType: 'image/*', // 图片类型
            data: fileData, // 文件内容(ArrayBuffer)
            remoteFileName: fileName // 文件名
          }
        ],
        expectDataType: http.HttpDataType.STRING // 预期返回数据类型
      },
      (err: BusinessError | undefined, data: http.HttpResponse) => {
        // 清理HTTP资源的函数
        const cleanup = () => {
          try {
            httpRequest.destroy();
            console.info('[HTTP] 请求资源已销毁');
          } catch (destroyError) {
            console.error('[HTTP] 销毁请求时出错:', destroyError);
          }
        };
        
        // 处理响应结果(根据实际业务需求实现)
        if (err) {
          resolve({ success: false, error: err.message });
        } else {
          resolve({ success: true, data: JSON.parse(data.result as string) });
        }
        
        // 清理资源
        cleanup();
      }
    );  
  });  
}
调用上传方法
typescript 复制代码
// 调用封装的上传接口
let result = await ApiService.updateAvatar(arrayBuffer, fileName);
// 处理上传结果
if (result.success) {
  console.info("图片上传成功");
} else {
  console.error("图片上传失败:" + result.error);
}

三、实现要点总结

  1. 权限处理 :使用PhotoViewPicker无需申请文件访问权限,仅访问用户明确选择的文件,更符合隐私保护要求。

  2. 数据流转

    • 客户端:URI → ArrayBuffer → 表单数据 → 服务端
    • 服务端:MultipartFile → 业务处理
  3. 关键匹配项

    • 客户端multiFormDataList中的name属性需与服务端@RequestParam的参数名一致(均为"file")
    • 内容类型需统一为multipart/form-data
  4. 资源管理:文件操作和网络请求完成后需及时释放资源,避免内存泄漏。

通过以上实现,鸿蒙5.1.1应用可以安全、高效地实现图片上传功能,兼顾用户体验与系统安全性。

相关推荐
爱笑的眼睛114 小时前
HarmonyOS应用开发:深入理解声明式UI与弹窗交互的最佳实践
华为·harmonyos
爱笑的眼睛1114 小时前
HarmonyOS 应用开发新范式:深入探索 Stage 模型与 ArkUI 声明式开发
华为·harmonyos
光锥智能18 小时前
小平板元年,华为MatePad Mini创出一片蓝海
华为·电脑
祥睿夫子18 小时前
零基础搞定 ArkTS 类与对象!保姆级教程:定义→创建→测试全流程 + 代码示例
harmonyos
程序员潘Sir21 小时前
HarmonyOS实现快递APP自动识别地址
harmonyos·鸿蒙
萌虎不虎21 小时前
【鸿蒙(openHarmony)自定义音频播放器的开发使用说明】
华为·音视频·harmonyos
李洋-蛟龙腾飞公司21 小时前
HarmonyOSAI编程万能卡片生成(一)
华为·ai编程·harmonyos
HarmonyOS_SDK1 天前
打破场景边界,支付宝联合实况窗提供全新出行服务体验
harmonyos