vue3,elementui vant 阿里Oss 直傳

上傳時計算文件hash 這樣可以減少成本
之前的邏輯是前端將文件上傳到業(yè)務服務器思灰,業(yè)務服務器計算hash康愤,已上傳的話直接返回hash對應的文件名稱儡循,沒有再上傳然后保存文件名稱于hash,這樣缺點就是服務器往阿里云還要傳一次征冷,比較費時
直傳的話計算出hash择膝,然后md5 再直接上傳覆蓋

export interface BaseResponse<T = undefined> {
  status: number
  data: T
  msg: string
}

// oss配置
export interface OssConfig {
  accessid: string
  host: string
  expire: number
  signature: string
  policy: string
  dir: string
}
/**
 * 從服務端獲取OSS配置
 * @returns {Promise<AxiosResponse<BaseResponse<OssConfig>>>>}
 */
export function ossConfig() {
    return axios.get('/oss/config');
}

/**
 * 初始化Oss配置
 * @returns {Promise<OssConfig>}
 */
export function initOssConfig() {
    return new Promise((resolve, reject) => {
        // 從本地localstore從獲取配置
        const conf = store.get('ossConfig')
        if (conf) {
          //  配置存在并且距離過期時間還大于3秒則返回此配置
            const now = new Date().getTime() / 1000
            if (conf.expire - 3 > now) {
                resolve(conf)
                return
            }
        }

        ElLoading.service({text: "獲取上傳配置"})

      // 請求接口返回配置數(shù)據(jù)
        ossConfig()
            .then((resp) => {
                if (resp.status === 0) {
                    resolve(resp.data);
                    // 配置數(shù)據(jù)寫入本地store
                    store.set('ossConfig', resp.data)
                } else {
                    reject(resp)
                    ElMessage.error("獲取上傳配置失敗")
                }
            })
            .catch((err) => {
                console.log(err);
                ElMessage.error("獲取上傳配置失敗")
                reject(err)
            })
    })
}

/**
 * 往Oss上傳文件
 * @param file File對象
 * @returns {Promise<{name:string,host:string}>}
 */
export  function  ossUpload(file) {
    return new Promise((resolve, reject) => {
        initOssConfig()
            .then(async (ossConf) => {
                const config = {
                    timeout: 1000 * 60 * 10,
                    headers: {'Content-Type': 'multipart/form-data'}
                }

                // 計算文件Hash 避免多余的文件上傳,這樣做的目的是盡量少占用OSS的空間
                const name = await fileHash(file) + fileSuffix(file.name)
                const formData = new FormData()
                const key = `${ossConf.dir}${name}`

                formData.append('name', name)
                formData.append('key', key)
                formData.append('policy', ossConf?.policy)
                formData.append('OSSAccessKeyId', ossConf?.accessid)
                formData.append('success_action_status', '200')
                formData.append('signature', ossConf.signature)
                formData.append('file', file)

                axios
                    .post(ossConf.host, formData, config)
                    .then((resp) => {
                        resolve({name: key, host: ossConf.host})
                    })
                    .catch((err) => reject(err))
            })
            .catch((err)=>{
                console.log(err);
                reject({msg: '上傳失敗'})
            })
    })
}
yarn add crypto-js
yarn add file-to-array-buffer
import { lib, SHA256 } from 'crypto-js'
import fileToArrayBuffer from 'file-to-array-buffer'

 // 獲取文件后綴
export function fileSuffix(filename) {
    const pos = filename.lastIndexOf('.')
    let suffix = ''
    if (pos !== -1) {
        suffix = filename.substring(pos)
    }
    return suffix;
}

export function arrayBufferToWordArray(ab) {
    const i8a = new Uint8Array(ab)
    const a = []
    for (let i = 0; i < i8a.length; i += 4) {
        a.push((i8a[i] << 24) | (i8a[i + 1] << 16) | (i8a[i + 2] << 8) | i8a[i + 3])
    }
    return lib.WordArray.create(a, i8a.length)
}

// 獲取文件Hash
export async function fileHash(file) {
    const buffer = await fileToArrayBuffer(file)
    return SHA256(arrayBufferToWordArray(buffer)).toString()
}

使用示例

element plus

用vant基本差不多

const handleBeforeUpload = (file) => {
      const loading = ElLoading.service({
        lock: true,
        text: '請稍后',
        background: 'rgba(0, 0, 0, 0.4)',
      })

      ossUpload(file)
          .then(({host,name}) => {
            loading.close();
          console.log(host + name)
          })
          .catch((err) => {
            console.log(err);
            loading.close();
            ElMessage.error("上傳文件失敗")
          })

      return false;
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末检激,一起剝皮案震驚了整個濱河市肴捉,隨后出現(xiàn)的幾起案子腹侣,更是在濱河造成了極大的恐慌,老刑警劉巖齿穗,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件傲隶,死亡現(xiàn)場離奇詭異,居然都是意外死亡窃页,警方通過查閱死者的電腦和手機跺株,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脖卖,“玉大人乒省,你說我怎么就攤上這事∑枘荆” “怎么了袖扛?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長馋劈。 經常有香客問我攻锰,道長,這世上最難降的妖魔是什么妓雾? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任娶吞,我火速辦了婚禮,結果婚禮上械姻,老公的妹妹穿的比我還像新娘妒蛇。我一直安慰自己,他們只是感情好楷拳,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布绣夺。 她就那樣靜靜地躺著,像睡著了一般欢揖。 火紅的嫁衣襯著肌膚如雪陶耍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天她混,我揣著相機與錄音烈钞,去河邊找鬼。 笑死坤按,一個胖子當著我的面吹牛毯欣,可吹牛的內容都是我干的。 我是一名探鬼主播臭脓,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼酗钞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起砚作,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤窘奏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后葫录,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔼夜,經...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年压昼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘤运。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡窍霞,死狀恐怖,靈堂內的尸體忽然破棺而出拯坟,到底是詐尸還是另有隱情但金,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布郁季,位于F島的核電站冷溃,受9級特大地震影響,放射性物質發(fā)生泄漏梦裂。R本人自食惡果不足惜似枕,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望年柠。 院中可真熱鬧凿歼,春花似錦、人聲如沸冗恨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掀抹。三九已至虐拓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間傲武,已是汗流浹背蓉驹。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谱轨,地道東北人戒幔。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像土童,于是被迫代替她去往敵國和親诗茎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內容