浏览代码

fix: hwobs

ryanemax 3 月之前
父节点
当前提交
c57d5f159e
共有 1 个文件被更改,包括 164 次插入0 次删除
  1. 164 0
      src/lib/storage/hwobs.service.ts

+ 164 - 0
src/lib/storage/hwobs.service.ts

@@ -0,0 +1,164 @@
+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"
+}
+
+/**
+ * HwobsService 华为OBS文件服务
+ * @public
+ */
+export class HwobsService {
+  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<HwobsDir>,
+    files:Array<HwobsFile>
+  }>{
+    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<Parse.Object>{
+    // 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,key)
+                resolve(attach)
+              }
+        });
+      })
+  }
+  Attachment = Parse.Object.extend("Attachment")
+
+  async checkFileExists(file:any):Promise<Parse.Object>{
+    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){
+    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);
+    });
+  }
+}