鸿蒙上传文件接口封装

209 阅读2分钟

上传文件是一个比较常见的接口,但鸿蒙文档里面没有详细说明,我这边是以论坛上的大佬相关文章结合实际情况对上传文件做了封装,

// pages/uploadFile.ets

import common from '@ohos.app.ability.common';
import request from '@ohos.request';
import { BusinessError } from '@ohos.base';
import { service_api } from './config';//你自己定义的接口域名
import { localStorage } from './GlobalContext';//参考缓存文章https://juejin.cn/post/7369019487624167435
import picker from '@ohos.file.picker';
import { generateRandomString, returnBundleInfo, ShowT, signInfo } from '../common';//一些公共方法库,其中用到版本信息,提示,生成随机数,生成加密数据,这个根据你定义的接口选择,下方对应的使用对应删除
import fs from '@ohos.file.fs';
import axios, { AxiosError, AxiosProgressEvent, AxiosResponse } from '@ohos/axios'
import { FormData } from '@ohos/axios'
import FaultLogger from '@ohos.faultLogger';
import { DialogUtil } from '../componment/dialog';//loading全局弹窗,这个我是问其他道友给的组件我,后续我会补充上
import { uploadFileType } from './type';//定义类型
import { ResponseResult } from './api';//定义类型

async function selectImg() {
  let photoSelectOptions = new picker.PhotoSelectOptions();
  photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
  photoSelectOptions.maxSelectNumber = 1;
  let photoPicker = new picker.PhotoViewPicker();

  try {
    let photoSelectResult = await photoPicker.select(photoSelectOptions);
    if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
      let imgUri = photoSelectResult.photoUris[0];
      if (imgUri.indexOf('media/Photo') < 0) {
        return '';
      }
      // console.log(imgUri,'imgUri')


      return imgUri;
    } else {
      return '';
    }
  } catch (err) {
    console.error('SelectedImage failed', JSON.stringify(err));
    return '';
  }
}

interface fileType {
  fileName: string,
  fileNameWithExtension: string
}

function getFileName(filePath: string): fileType {
  // 通过分割路径字符串获取文件名部分
  const parts = filePath.split('/');
  const fileNameWithExtension: string = parts[parts.length - 1];

  // 分割文件名和扩展名
  const fileNameParts = fileNameWithExtension.split('.');
  // 取出文件名部分
  const fileName: string = fileNameParts[0];

  return { fileName, fileNameWithExtension };
}


let context = getContext(this) as common.UIAbilityContext;
let cacheDir = context.cacheDir;
const uploadFile =  (uri:string): Promise<uploadFileType> => {
  return new Promise(async(resolve:Function,reject:Function)=>{
    DialogUtil.showLoading();
    setTimeout(() => {
      DialogUtil.hideLoading()
    }, 10000)
    console.log('uploadFile')
    let formData = new FormData();
    let nonce_str = generateRandomString()
    let bundleInfo = await returnBundleInfo();
    let colorToken = await localStorage.getItem('token') as string
    let getParams: string = `version=${bundleInfo.versionName
    }&nonce_str=${nonce_str
    }&native_type=3`
    let signature = signInfo(getParams)

    console.log('up')
    let file = fs.openSync(uri, fs.OpenMode.CREATE);
    // 复制文件到缓存目录下
    fs.copyFileSync(file.fd, context.cacheDir + '/' + getFileName(uri).fileNameWithExtension)
    // let file = fs.openSync(uri);
    console.info("upload", `file fd -> ${file.fd}`);
    console.info("upload", `file path -> ${file.path}`);
    try {
      let stat = fs.lstatSync(context.cacheDir + '/' + getFileName(uri).fileNameWithExtension);
      console.info("upload", JSON.stringify(stat.size));
      let buf = new ArrayBuffer(stat.size);
      fs.readSync(file.fd, buf);
      fs.fsyncSync(file.fd);
      console.info("upload", `buf -> ${JSON.stringify(buf)}`);
      formData.append("img", buf,getFileName(uri).fileNameWithExtension);
      //这里是你定义的接口文件名称地址,我这里定义的是img,当然大部分是file,你根据情况修改就行
    }catch (e){
      console.info(JSON.stringify(e))
    }
    //这里是你额外的参数,我这边是有以下4个参数,你根据你的情况来,也可以将接口链接,传参,值,用一个对象传参处理,
    formData.append('version', bundleInfo.versionName)
    formData.append('nonce_str', nonce_str)
    formData.append('native_type', '3')
    formData.append('signature', signature)
    // console.log('uploadFile',JSON.stringify(formData))
    formData.forEach((v: Object) => {
      console.info("upload", `formData -> ${JSON.stringify(v)}`);
    })
    //http://192.168.90.96:3000/upload
    //${service_api}/app/user/portrait

    try {
      let res:AxiosResponse =await axios.post(`${service_api}/app/user/portrait`, formData, {
        headers: {
          'Accept': '*/*',
          'Content-Type': 'multipart/form-data',
          'color-token': colorToken
        },
        context: getContext(context),
        onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
          console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
        },
      })
     
      DialogUtil.hideLoading()
      console.log(JSON.stringify(res.data),`${service_api}/app/user/portrait`,'response')
      if(res.data && res.data.code==0){
        resolve(res.data.content)
      }else {
        ShowT.shortToast(res.data.msg)
        reject(res.data)
      }

    }catch (error){
      reject(error)
    }
  })


}

export { uploadFile, selectImg }

那么如何使用这个功能呢

selectImg().then(res=>{

  uploadFile(res).then((info:uploadFileType)=>{
    console.log(JSON.stringify(info))
    if(info.img){
      ShowT.shortToast('上传成功')
    }
  })
})

所以,将以上方法封装之后,后续调用这个功能的时候就可以用两个异步函数处理就行啦,

PS:暂时没做上传状态的处理,暂时也只能上传图库图片+拍摄后的图片,