首页 > 其他分享 >vue3.0 + ts 实现上传工厂(oss与cos)

vue3.0 + ts 实现上传工厂(oss与cos)

时间:2023-11-06 16:36:46浏览次数:41  
标签:cos string data oss bucket ts export import type

概述

将上传基类命名为MOS(Mine Object Storage)

mos.ts代码

import {MosType} from './mosConfig'
import {Loading} from '../loading'
import {type BinaryFile, type MosFile} from './fileUtil'
import type { PathTemplate } from './pathTemplate'
import axios, { type AxiosResponse } from 'axios'
import {loadUser} from '../user'
export interface MosSettings{
    cdn:string | null
    bucket:string
    endpoint:string
}

export interface UploadOptions{
    cover:boolean 
    progress?:Function
    failed?:Function
}

export abstract class Mos{
    settings : MosSettings
    finished : boolean = false
    loading : Loading
    pathTemplate:string 

    constructor(settings:MosSettings,template:PathTemplate){
        this.settings = settings
        this.loading = new Loading()
        this.pathTemplate = `${template.appId}/@ownerId/@fileName`
    }

    abstract init() : void

    abstract uploadFile(file:BinaryFile,options:UploadOptions,token:string) : Promise<MosFile|null>

    async upload(file:BinaryFile,options:UploadOptions) : Promise<MosFile|null> {
        const user=loadUser()
        this.pathTemplate=this.pathTemplate.replace('@ownerId',user?.userId.toString() ?? '0')
        return await this.uploadFile(file,options,user?.token ?? '')
    }

    async getCredential(token:string,bucket:string,type: MosType) : Promise<AxiosResponse<any, any>>{
        const params = { bucket: bucket, ossSource: type }
        const url = `https://api.mos.com/api/v1/Credential` // 接口会根据不同的ossSource参数值返回不同的数据结构,因此可以放在基类

        return axios.get(url, { params ,headers:{
            'Authorization':token,
            'Content-Type':'application/json'
        }})
    }
}

oss.ts代码

import axios from "axios";
import type { BinaryFile, MosFile } from "./fileUtil";
import { Mos, type UploadOptions } from "./mos";
import { MosType, type OssConfig } from "./mosConfig";
import type { OssCredential } from "./mosCredential";
import type { PathTemplate } from "./pathTemplate";

export class Oss extends Mos{
    policy : string = ''
    signature : string = ''
    accessKeyId:string
    host:string

    constructor(config:OssConfig,template:PathTemplate) {
        super({bucket:config.bucket,endpoint:config.endpoint,cdn:config.cdn},template)
        this.accessKeyId = config.accessKeyId
        this.host=`https://${config.bucket}.${config.endpoint}`
    }

    init() {
        return
    }

    async getSTSToken(token:string){
        if (this.policy) return Promise.resolve()
        
        return await this.getCredential(token,this.settings.bucket,MosType.Oss).then(result => {
            const data = result.data.data as OssCredential;
            this.policy = data.policy;
            this.signature = data.signature;
        })
    }

    async uploadFile(file: BinaryFile, options: UploadOptions,token:string): Promise<MosFile|null> {
        this.finished = false
        this.loading.startLoading()
        await this.getSTSToken(token)
        const fileName = file.name
        const ossPrefix = 'TempFiles/'
        const saveKey = ossPrefix + this.pathTemplate.replace('@fileName',fileName)

        const formData = new FormData();
        formData.append("policy", this.policy);
        formData.append("Signature", this.signature);
        formData.append("bucket", this.settings.bucket);
        formData.append("key", saveKey);
        formData.append("OSSAccessKeyId", this.accessKeyId);
        formData.append("success_action_status", "201");

        formData.append("Content-Disposition", "attachment;filename=" + fileName + ";filename*=UTF-8''" + fileName);
        formData.append("file", file.binary);

        return axios.post(this.host, formData, {
            responseType: 'document',
            onUploadProgress: evt => options.progress && options.progress(evt),
        }).then(result => {
            this.finished = true;
            this.loading.endLoading();

            console.log("上传成功");

            const data = result.data;
            const url = data.getElementsByTagName("Location")[0].childNodes[0].nodeValue;

            return url ? Promise.resolve({ url,  fileName }) : Promise.reject(result);
        }).catch(error => {
            this.finished = true;
            this.loading.endLoading()

            console.log("上传失败");

            options.failed &&options.failed(error);

            return null
        })
    }    

}

cos.ts 代码

import type { BinaryFile, MosFile } from './fileUtil'
import { Mos, type UploadOptions } from './mos'
import { MosType, type CosConfig } from './mosConfig'
import type { PathTemplate } from './pathTemplate'
import COS from 'cos-js-sdk-v5'
import type { CosCredential } from './mosCredential'

export class TencentCOS extends Mos {
  cos: COS | null = null
  currentToken:string = ''

  constructor(config: CosConfig, template: PathTemplate) {
    super({ bucket: config.bucket, endpoint: config.endpoint, cdn: config.cdn }, template)
  }

  init() {
    this.cos = new COS({
      getAuthorization:  (options, callback) => this.getAuthorizationCredential(callback),
      UploadCheckContentMd5: true 
    })
  }
  async uploadFile(file: BinaryFile, options: UploadOptions, token: string): Promise<MosFile | null> {
    this.currentToken = token
    this.finished = false;
    this.loading.startLoading()
    const fileName = file.name
    const savekey = this.pathTemplate.replace('@fileName',fileName)
    return new Promise((resolve, reject) => {
        this.cos!.uploadFile({
            Bucket: this.settings.bucket,
            Region: this.settings.endpoint,
            Key: savekey,
            Body: file.binary,
            SliceSize: 1024 * 1024 * 5, 
            Headers: {
                'content-disposition': "attachment;filename=" + fileName + ";filename*=UTF-8''" + fileName
            },
            onProgress: evt => options.progress && options.progress(evt),
        }, (err, data) => {
            this.finished = true;
            this.loading.endLoading()

            if (err) {
                console.log("上传失败");
                options.failed && options.failed(err);
                reject(err);
            }
            if (data) {
                console.log("上传成功");
                resolve({ url, fileName });
            }
        });
    })
  }

  getAuthorizationCredential(callback:Function){
      this.getCredential(this.currentToken, this.settings.bucket, MosType.Cos).then((result) => {
      const data = result.data.data as CosCredential
      callback({
        TmpSecretId: data.tmpSecretId,
          TmpSecretKey: data.tmpSecretKey,
          SecurityToken: data.token,
          StartTime: data.startTime,
          ExpiredTime: data.expiredTime
      })
    })
  }

}

mosFactory.ts 代码

import { TencentCOS as Cos } from "./cos";
import type { Mos } from "./mos";
import {MosConfig, MosType } from "./mosConfig";
import { Oss } from "./oss";
import type { PathTemplate } from "./pathTemplate";

export function CreateMos (template:PathTemplate,type:MosType = MosType.Cos) : Mos {
    const config:MosConfig = new MosConfig()
    let mos:Mos 
    switch (type) {
        case MosType.Cos:
            mos= new Cos(config.cos,template)
            break;
        case MosType.Oss:
            mos= new Oss(config.oss,template)
            break
        default:
            mos= new Cos(config.cos,template)
            break;
    }
    mos.init()

    return mos
}

export function CreateDefaultMos(type:MosType = MosType.Cos) : Mos {
    return CreateMos({appId:'demo'},type)
}

其他代码

PathTemplate.ts

export interface PathTemplate{
    appId:string //应用Id 
}

mossCredential.ts

export interface OssCredential{
    policy:string
    signature:string
    accessKeyId:string|null
}

export interface CosCredential{
    tmpSecretId:string
    tmpSecretKey:string
    token:string
    startTime:number
    expiredTime:number
}

fileUtil.ts

export interface MosFile {
  url: string | null
  fileName: string
}

export interface BinaryFile{
  binary: Blob
  name:string
}

mosConfig.ts

export interface OssConfig {
  isTemp: boolean
  bucket: string
  endpoint: string
  cdn: string
  accessKeyId: string
}
export interface CosConfig{
    bucket: string
    endpoint: string
    cdn: string
}

export class MosConfig {
  oss: OssConfig = {
    bucket: 'demo-bucket',
    endpoint: 'oss-cn.aliyuncs.com',
    cdn: '',
    accessKeyId: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  }
  cos:CosConfig = {
    bucket: 'demo-bucket',
    endpoint: 'beijing',
    cdn: ""
  }
}

export enum MosType{
    Oss = 1,
    Cos
}

在vue3.0是使用

在App.vue中

import {provide} from 'vue'
import {CreateDefaultMos} from './assets/ts/mos/mosFactory'

provide('mos',CreateDefaultMos())

在组件中注入使用

import {inject } from 'vue'

const mos:Mos = inject('mos')!

标签:cos,string,data,oss,bucket,ts,export,import,type
From: https://www.cnblogs.com/Saints/p/17813016.html

相关文章

  • CF1861F Four Suits【网络流,贪心】
    有\(n\)个人,\(4\)种不同的卡牌,初始第\(i\)个人有\(a_{i,j}\)张第\(j\)种卡牌。你是局外人,手里第\(j\)种卡牌有\(b_j\)个,你现在要把你的卡牌分给这\(n\)个人,使得分完之后每个人手里的卡牌总数相等,保证有解。第\(i\)个人最终的分数是手里每种卡牌的数量的最大值......
  • MySQL: Speed of INSERT Statements
    SpeedofINSERTStatementsTooptimizeinsertspeed,combinemanysmalloperationsintoasinglelargeoperation.Ideally,youmakeasingleconnection,sendthedataformanynewrowsatonce,anddelayallindexupdatesandconsistencycheckinguntilthe......
  • vue视频直接播放rtsp流;vue视频延迟问题解决;webRTC占cpu太大卡死问题解决;解决webRTC播
    vue视频直接播放rtsp流;vue视频延迟问题解决;webRTC占cpu太大卡死问题解决;解决webRTC播放卡花屏问题::https://blog.csdn.net/killerdoubie/article/details/133884070......
  • Flask_微服务-Nacos
    微服务微服务通常需要通过REST或gRPC等协议相互通信,由于我们可能同时与多个微服务通信 Nacos-服务注册、发现与配置中心https://github.com/alibaba/nacos传统的单元应用架构开始朝着微服务架构方向演进。演进过程中首要问题就是微服务如何相互发现对方进行调用?我......
  • 【转载】The Beginner’s Guide to Creating and Selling Cheat Sheets
    【from】https://medium.com/practice-in-public/the-beginners-guide-to-creating-and-selling-cheat-sheets-23756af06b12Thisis10xbetterthanyour50-pageebookHaveyoueverwishedyoucouldcutthroughthenoiseandgettotheheartofatopicquickly?E......
  • How to resize slide dimensions without resizing any objects on the slide?
    IFyouarecompetenttounzipthepptxfileandmodifytheXMLitcanbedone,theslidesizewillchangebutthepictureswillnotchange(theywillmovethoughandyouwillhavetoadjustthepositions)Unzip>lookforPPT>presentationXMLandc......
  • Unity DOTS中ECS核心架构详解
    最近DOTS终于发布了正式的版本, 我们来分享一下DOTS中ECS的几个关键概念与结构,方便大家上手学习掌握Unity DOTS开发。 ECS中的World  Unity DOTS ECS架构中所有的Entity都是被放到了World对象里面,每个Entity在World里面都有唯一的Id号。Unity DOTS 可以同时支持很多个......
  • LangChain=>RecursiveCharacterTextSplitter
     .Net版本LangChain源码:github.comRecursiveCharacterTextSplitter调用方法:varstate_of_the_union_txt="text-Content";vartextSplitter=newRecursiveCharacterTextSplitter(chunkSize:300,chunkOverlap:30);vartexts=textSplitter.CreateDocuments(n......
  • VMware Workstation 15 Pro 安装macOS 10.15 Catalina (cdr文件版)
    VMwareWorkstation15Pro安装macOS10.15Catalina(cdr文件版) 所需工具:1.VMwareworkstation15Pro2.Unlocker (https://github.com/paolo-projects/unlocker/releases)https://github.com/paolo-projects/unlocker/releases/download/3.0.3/unlocker.zip3.macOScdr安......
  • mstsc远程报:这可能是由于CredSSP 加密Oracle修正的两种完美解决方法
      解决方法gpedit.msc  计算机配置>管理模板>系统>凭据分配>加密Oracle修正   ......