import { Injectable } from '@angular/core'; // @ts-ignore import ObsClient from "esdk-obs-browserjs" import Parse from "parse"; /** * HwobsDir 华为OBS目录接口 * @public */ export interface HwobsDir { Prefix: string // "storage/2023/" } /** * HwobsDir 华为OBS文件接口 * @public */ export interface HwobsFile { ETag: "\"f0ec968fe51ab48348307e06476122eb\"" Key: string //"storage/3mkf41033623275.png" LastModified: string //"2023-11-08T12:03:13.008Z" Owner: object // {ID: '09971a1979800fb60fbbc00ada51f7e0'} Size: string //"25839" StorageClass: string //"STANDARD" } /** * HwobsProvider 华为OBS文件服务 * @public */ export class HwobsProvider { obsClient: ObsClient bucketName: string host: string globalPrefix: string = "" constructor(options: { host: string bucketName: string access_key_id: string secret_access_key: string prefix?: string server?: string }) { this.globalPrefix = options.prefix || "" this.host = options?.host this.bucketName = options?.bucketName this.obsClient = new ObsClient({ access_key_id: options.access_key_id, secret_access_key: options.secret_access_key, // 这里以华南-广州为例,其他地区请按实际情况填写 server: options?.server || 'https://obs.cn-south-1.myhuaweicloud.com' }); } /** * 目录及检索相关函数 */ listDir(prefix: any): Promise<{ dirs: Array, files: Array }> { return new Promise((resolve, reject) => { this.obsClient.listObjects({ Bucket: this.bucketName, Prefix: prefix, Delimiter: '/' }, (err: any, result: any) => { if (err) { console.error('Error-->' + err); reject(err) } else { console.log('Status-->' + result.CommonMsg.Status); console.log(result) if (result.CommonMsg.Status < 300 && result.InterfaceResult) { for (var j in result.InterfaceResult.Contents) { console.log('Contents[' + j + ']:'); console.log('Key-->' + result.InterfaceResult.Contents[j]['Key']); console.log('Owner[ID]-->' + result.InterfaceResult.Contents[j]['Owner']['ID']); } } let dirs: HwobsDir[] = result.InterfaceResult.CommonPrefixes let files: HwobsFile[] = result.InterfaceResult.Contents resolve({ dirs: dirs, files: files }) } }); }) } /** * 文件上传相关函数 * @param file * @param key * @returns */ async uploadFile(file: File, key: string): Promise { console.log(this.globalPrefix, key) // key 文件上传后的全部路径 // /storage/<公司账套>/<应用名称>/年月日/<文件名>.<文件后缀> // /storage/web2023/<学号>/年月日/<文件名>.<文件后缀> let attach = await this.checkFileExists(file); if (attach?.id) return attach return new Promise((resolve, reject) => { this.obsClient.putObject({ Bucket: this.bucketName, Key: this.globalPrefix + key, SourceFile: file }, async (err: any, result: any) => { if (err) { console.error('Error-->' + err); reject(err) } else { console.log('Status-->' + result.CommonMsg.Status); let attach = await this.saveAttachment(file, this.globalPrefix + key) const fileUrl = this.host + this.globalPrefix + key; console.log(fileUrl) resolve(attach) } }); }) } Attachment = Parse.Object.extend("Attachment") async checkFileExists(file: any): Promise { let hash = await this.getFileHash(file) // 文件HASH查重,避免重复上传 let attach: Parse.Object let query = new Parse.Query("Attachment") query.equalTo("hash", hash); query.equalTo("size", file.size); let exists: any = await query.first(); if (!exists?.id) exists = new this.Attachment() attach = exists return attach } async saveAttachment(file: File, key: string) { console.log("saveAttachment", key) let hash = await this.getFileHash(file) let attach = await this.checkFileExists(file) attach.set("name", file.name) attach.set("size", file.size) attach.set("mime", file.type) attach.set("url", this.host + key) attach.set("hash", hash) attach = await attach.save() return attach } async getFileHash(file: File) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = async (event: any) => { const buffer = event.target.result; const hashBuffer = await crypto.subtle.digest('SHA-256', buffer); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join(''); resolve(hashHex); }; reader.onerror = (event: any) => { reject(event.target.error); }; reader.readAsArrayBuffer(file); }); } }