OSSUploadManager.ets 7.05 KB
import { NetLayerOSSConfigInfoModel, NetLayerOSSToken } from 'wdBean'
import { HostEnum, HttpParams, HttpUrlUtils, ResponseDTO } from 'wdNetwork'
import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'
import { data } from '@kit.TelephonyKit'
import { DateTimeUtils, DeviceUtil, Logger } from 'wdKit'
import { MultipartUpload } from './multipartUpload'
import { OSSConfig } from './OSSConfig'
import { http } from '@kit.NetworkKit'
import { it } from '@ohos/hypium'
import { putObject } from './upload'

export enum OSSConfigSceneType {
  feedback = "feedback",

}

export enum OSSFileType {
  image = 0,
  video = 1,
}

export class OSSUploadResult {
  ossFile?: string
}

export class UploadResourceParams {
  fileUri: string = ''
  scene: OSSConfigSceneType = OSSConfigSceneType.feedback
  fileType: OSSFileType = OSSFileType.image

  constructor(fileUri: string) {
    this.fileUri = fileUri
  }
}

const TAG = "OSSUploadManager"

export class OSSUploadManager {

  private ossToken?: NetLayerOSSToken
  private configInfos?: Array<NetLayerOSSConfigInfoModel>

  private constructor() { }
  private static manager: OSSUploadManager
  static sharedManager(): OSSUploadManager {
    if (!OSSUploadManager.manager) {
      OSSUploadManager.manager = new OSSUploadManager()
    }
    return OSSUploadManager.manager
  }

  uploadFiles(inputs: Array<UploadResourceParams>) : Promise<Array<OSSUploadResult>> {
    return new Promise(async (resolve, fail) => {
      await this.getOssToken()
      await this.getOssConfigInfo()

      Promise.allSettled(inputs.map((item): Promise<OSSUploadResult> => {
        return this.uploadFile(item.fileUri, item.scene, item.fileType)
      })).then(res => {
        const failedJobs = res.filter(v => v.status === 'rejected');

        if (failedJobs.length > 0) {
          console.info('Failed objects: ' + failedJobs.length);
          resolve([])
        } else {
          console.info('All the objects upload success');
          let results: Array<OSSUploadResult> = [] as Array<OSSUploadResult>
          res.forEach((item) => {
            console.info('>>>>>' + JSON.stringify(item));
            if (item.status === 'fulfilled') {
              results.push(item.value)
            }
          })
          resolve(results)
        }
      })
    })
  }

  uploadFile(fileUri: string, scene: OSSConfigSceneType, fileType: OSSFileType) : Promise<OSSUploadResult> {
    return new Promise(async (success, fail) => {

      try {
        let tokenModel = await this.getOssToken()

        let config = await this.getOssConfigInfo()
        let configModuel = config?.filter((c) => {
          return c.type == scene
        }).pop()

        if (!configModuel) {
          Logger.warn(TAG, "配置为空")
          return
        }

        //格式样例 zhbj/img/social/2024080215/BA6690B9CF084B3FAEEFA58F100F8D3E.jpg,这里的格式目前和iOS 是保持一致的
        let objectName = configModuel.uploadPath + DateTimeUtils.getCurDate('yyyyMMddHH') + "/" + DeviceUtil.getRandomUUIDForTraceID() +  (fileType == OSSFileType.image ? ".jpg" : ".mp4")
        Logger.debug(TAG, `==>> ${fileUri} `)
        Logger.debug(TAG, `==>> endPoint: ${configModuel.endPoint} `)
        Logger.debug(TAG, `==>> bucketName: ${configModuel.bucketName} `)
        Logger.debug(TAG, `==>> objectName: ` + objectName)
        Logger.debug(TAG, JSON.stringify(tokenModel))
        Logger.debug(TAG, JSON.stringify(configModuel))

        let result = await this.upload(fileUri, configModuel.endPoint, configModuel.bucketName, objectName)

        if (result) {
          let r = {} as OSSUploadResult
          r.ossFile = objectName

          let url = configModuel.domain + "/" + objectName
          console.log("result url: " + url)
          success(r)
          return
        }

        Logger.error(TAG, "上传失败")
        fail("上传失败")

      } catch (e) {

        Logger.error(TAG, "上传失败" + JSON.stringify(e))
        fail("上传失败")
      }
    })
  }

  private upload(fileUri: string, endpoint:string, bucketName:string, objectName:string) : Promise<boolean> {

    return new Promise(async (reslove, fail) => {

      if (!this.ossToken || !this.ossToken.securityToken) {
        fail("missing accessKeyId or accessKeySecret or sessionToken")
        return
      }

      let config: OSSConfig = {
        stsToken: this.ossToken.securityToken,
        bucket: bucketName,
        fileName: objectName,
        accessKeyId: this.ossToken.accessKeyId,
        accessKeySecret: this.ossToken.accessKeySecret,
        customHeaders: HttpParams.buildHeaders(),
        serverUrl: this.getServerHost() + "/api/harmonyoss/get_sign_url"
      }

      let success = false
      try {
        const multipartUpload = new MultipartUpload(config, fileUri);

        let result: http.HttpResponse = await multipartUpload.multipartUpload();
        Logger.debug(TAG, "表单上传完成 + " + JSON.stringify(result))

        if (result.responseCode == 200) {
          success = true
        }

        // await putObject(fileUri, config)
        //
        // success = true

      } catch (e) {
        Logger.error(TAG, JSON.stringify(e))
      } finally {
        reslove(success)
      }
    })
  }

  private getOssToken():Promise<NetLayerOSSToken | undefined> {
    return new Promise<NetLayerOSSToken | undefined>((success, fail) => {

      if (this.ossToken && this.ossToken.securityToken.length > 0) {

        // this.ossToken.expiration
        let dateNumber = DateTimeUtils.parseDate(this.ossToken.expiration, DateTimeUtils.PATTERN_DATE_TIME_HYPHEN)
        if (Date.now() < (dateNumber - 60 * 1000)) {
          success(this.ossToken)
          return
        }
      }

      HttpRequest.get<ResponseDTO<NetLayerOSSToken>>(
        HttpUrlUtils.getOSSTokenUrl(),
      ).then((res: ResponseDTO<NetLayerOSSToken>) => {
        if (res.code != 0) {
          fail(res.message)
          return
        }

        this.ossToken = res.data
        success(res.data)
      }, (error: Error) => {
        fail(error.message)
      })
    })
  }

  private getOssConfigInfo() {
    let isAbroad = 0
    return new Promise<Array<NetLayerOSSConfigInfoModel> | undefined>((success, fail) => {
      if (this.configInfos && this.configInfos.length > 0) {
        success(this.configInfos)
        return
      }
      HttpRequest.get<ResponseDTO<Array<NetLayerOSSConfigInfoModel>>> (
        HttpUrlUtils.getOSSConfigInfoUrl()+ '?type=0'
      ).then((res: ResponseDTO<Array<NetLayerOSSConfigInfoModel>>) => {
        if (res.code != 0) {
          fail(res.message)
          return
        }
        this.configInfos = res.data
        success(res.data)
      })
    })
  }

  private getServerHost() {
    return HttpUrlUtils.getHost()
    // switch (HttpUrlUtils.getHost()) {
    //   case HostEnum.HOST_UAT: {
    //     return "https://pd-people-uat.pdnews.cn"
    //   }
    //   case HostEnum.HOST_DEV: {
    //     return "https://pd-people-dev.pdnews.cn"
    //   }
    //   case HostEnum.HOST_SIT: {
    //     return "https://pd-people-sit.pdnews.cn"
    //   }
    // }
    // return "https://www.peopleapp.com"
  }

}