斷點(diǎn)續(xù)傳湾宙,react/vue通用

? // 一 虐唠、第一個函數(shù)(file前置處理函數(shù))

customRequest: async (params: { file }) => {

? setLoading(true) // 開啟頁面loading,避免切片大文件期間用戶亂點(diǎn)靡菇,每個項(xiàng)目開啟loading的api不同昌讲,不一定是setLoading

? const { file } = params // 拿到file

? const { size, type, name } = file // 解構(gòu)出可能用到的幾個屬性

? // 1.格式判斷(types是props參數(shù)国夜,是支持的格式數(shù)組减噪,例:types: ['jpg', 'png', 'bmp', 'jpeg'])短绸,如果不需要做格式限制,可以不寫第一條的代碼

? if (types.length !== 0) {

? ? const fileExt = /\.([0-9a-zA-Z]+)$/i.exec(name)[1] // 獲取后綴

? ? const reg = new RegExp(`(${types.join('|')})$`)

? ? if (!reg.test(type) && !reg.test(fileExt)) {

? ? ? setLoading(false) // 關(guān)閉loading

? ? ? message.error(messageError) // 格式不對提示頁面提示筹裕,提示語messageError也是props傳進(jìn)來的參數(shù)醋闭,也可以直接寫死幾個字如“格式不正確”

? ? ? return false

? ? }

? }

? // 2.大文件判斷(maxSize是props參數(shù),讓用戶自定義限制最大上傳文件大谐洹)

? if (size > maxSize * 1024 * 1024) {

? ? setLoading(false) // 關(guān)閉loading

? ? message.error('文件格式或大小不符合要求证逻,請重新上傳!')

? ? return false

? }

? // 3.獲取文件md5值(文件的md5值是根據(jù)文件內(nèi)容生成的一個單獨(dú)的標(biāo)示抗斤,需要安裝并引入一個插件:import SparkMD5 from 'spark-md5')

? const result: any = await fileParse(file, 'buffer') // fileParse轉(zhuǎn)換函數(shù)我附在最下面??囚企,將file轉(zhuǎn)成buffer格式數(shù)據(jù),

? const spark = new SparkMD5.ArrayBuffer()

? spark.append(result)

? const hash = spark.end() // 獲取到的文件md5值

? // 4.重復(fù)文件判斷

? ? ? ?/** 如果重復(fù)直接提示并return瑞眼,此部分代碼根據(jù)框架不同自己寫龙宏,如果不需要做去重可不寫,這里就不貼出來了…… **/

? // 5.文件切片上傳

? const partSize = 5 * 1024 * 1024 // 考慮到前后端上傳效率伤疙,我這里是切成5M/片,這個可根據(jù)項(xiàng)目實(shí)際需要自己決定

? const share = size <= partSize ? 1 : size / partSize // 判斷如果文件<=5M,不切片银酗,超過按照5M每份切

? let cur = 0

? const partList = [] // 存儲文件切片的數(shù)組

? for (let i = 0; i < share; i++) {

? ? const obj = {

? ? ? file: file.slice(cur, cur + partSize), // 調(diào)用file.slice方法進(jìn)行file的切片,第一個參數(shù)從哪里開始切徒像,第二個參數(shù)切到哪里

? ? ? id: i + 1 // 每一個切片的單獨(dú)標(biāo)示黍特,后期續(xù)傳時用與去除已上傳部分的切片

? ? }

? ? partList.push(obj) // 把切的每一片統(tǒng)一放到一個數(shù)組里

? ? cur += partSize

? }

? isOpen = true // isOpen代表上傳開關(guān),true標(biāo)示打開上傳開關(guān)锯蛀,false標(biāo)示關(guān)閉上傳開關(guān)灭衷,你可以定義不同的名字,并且在哪里定義看你所用的框架

? setLoading(false) // 關(guān)閉loading

? // 6.調(diào)用斷點(diǎn)續(xù)傳

? register(partList, hash, name) // 此函數(shù)往下看??

},

// 二 旁涤、 第二個函數(shù)(注冊上傳任務(wù)函數(shù) -- 調(diào)用第一個接口翔曲,注冊上傳任務(wù)接口)

const register = (partList, hash, fileName) => {

// 1.調(diào)第一個接口经备,上傳任務(wù)注冊接口,參數(shù)需要將文件的md5傳過去部默,后臺專門根據(jù)此文件開啟一個上傳任務(wù)(一個文件對應(yīng)一個上傳任務(wù))

taskRegistration({ fileMd5: hash })

? .then((res) => {

? ? const { uploadId, status, partNumSet } = res.data // uploadId是與這個文件對應(yīng)的上傳任務(wù)的id標(biāo)示侵蒙,status是此文件的狀態(tài),如已上傳部分切片||從未進(jìn)行上傳傅蹂,這是第一次||已經(jīng)上傳完了還未進(jìn)行合并纷闺,partNumSet是一個數(shù)組,里面放著已經(jīng)上傳的切片的id份蝴,如果是從未進(jìn)行上傳犁功,就是空數(shù)組

? ? const mergeParame = { hash, uploadId, fileName }

? ? if (status === 1) { // 1.已全部上傳,未合并婚夫,直接調(diào)合并函數(shù)

? ? ? complete(mergeParame)

? ? } else if (status === 2) { // 2.已上傳部分浸卦,根據(jù)后臺返回的partNumSet字段(已上傳切片id的數(shù)組)篩選,去除已上傳部分案糙,把剩下的切片組成一個新數(shù)組限嫌,如果篩選出來的新數(shù)組長度是0說明切片都已上傳,直接合并时捌,否則調(diào)用上傳切片函數(shù)

? ? ? const newPartList = []

? ? ? partList.forEach((item) => {

? ? ? ? if (partNumSet.indexOf(`${item.id}`) === -1) {

? ? ? ? ? newPartList.push(item)

? ? ? ? }

? ? ? })

? ? ? if (newPartList.length === 0) {

? ? ? ? complete(mergeParame)

? ? ? } else {

? ? ? ? newRequestArr(newPartList, hash, fileExt, uploadId, mergeParame)

? ? ? }

? ? } else if (status === 3) { // 3.從未上傳過此文件怒医,調(diào)用上傳切片函數(shù)

? ? ? newRequestArr(partList, hash, fileExt, uploadId, mergeParame)

? ? }

? })

}

// 三 、 第三個函數(shù)(上傳切片函數(shù) -- 調(diào)用第二個接口奢讨,上傳文件切片接口)

const newRequestArr = (partList, hash, fileExt, uploadId, mergeParame) => {

let i = 0

const fn = () => {

? const formData = new FormData() // 通過form將file切片傳給后臺

? formData.append('file', partList[i].file)

? formData.append('fileMd5', hash)

? formData.append('fileExt', fileExt)

? formData.append('uploadId', uploadId)

? formData.append('partNumber', partList[i].id)

? sliceUpload(formData).then(() => {

? ? if (isOpen.current) { // 如果上傳開關(guān)在這里是false稚叹,則會停止遞歸調(diào)用上傳函數(shù),至于在哪里把他置為false拿诸,看你在哪里點(diǎn)擊觸發(fā)的暫桶切洌或者刪除上傳函數(shù)了,自己決定

? ? ? i += 1

? ? ? if (i < partList.length) {

? ? ? ? fn()

? ? ? } else {

? ? ? ? complete(mergeParame) // 如果是最后一個切片亩码,則調(diào)用合并函數(shù)

? ? ? }

? ? }

? })

}

fn()

}

// 四 季率、 第四個函數(shù)(文件合并函數(shù) -- 調(diào)用第三個接口,文件合并接口)

const complete = (mergeParame) => {

fileMerge(mergeParame).then((res) => {

? const { status, fileId } = res.data

? if (status === 1) {

? ? message.error('上傳失敗蟀伸,請重試蚀同!')

? ? return

? }

? if (status === 2) {

? ? message.error('有其它用戶正在上傳該文件,請稍后重試啊掏!')

? ? return

? }

})

}

// 轉(zhuǎn)換函數(shù)

const fileParse = (file, type = 'base64') => {

return new Promise((res) => {

const fileReader = new FileReader()

/* fileReader.readAsArrayBuffer() // 轉(zhuǎn)成buffer格式數(shù)據(jù)

? fileReader.readAsBinaryString() // 轉(zhuǎn)成二進(jìn)制格式數(shù)據(jù)

? fileReader.readAsDataURL() // 轉(zhuǎn)成base64格式數(shù)據(jù)

? 解析過程是異步蠢络,所以需要調(diào)用onload事件的e.target.result獲取轉(zhuǎn)換后的結(jié)果

*/

switch (type) {

? case 'base64':

? ? fileReader.readAsDataURL(file)

? ? break

? case 'buffer':

? ? fileReader.readAsArrayBuffer(file)

? ? break

? case 'binary':

? ? fileReader.readAsBinaryString(file)

? ? break

? default:

? ? break

}

fileReader.onload = (e) => {

? res(e.target?.result)

}

})

}



文章出處

https://blog.csdn.net/qq_45043019/article/details/115899304

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市迟蜜,隨后出現(xiàn)的幾起案子刹孔,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件髓霞,死亡現(xiàn)場離奇詭異卦睹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)方库,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門结序,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纵潦,你說我怎么就攤上這事徐鹤。” “怎么了邀层?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵返敬,是天一觀的道長。 經(jīng)常有香客問我寥院,道長劲赠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任秸谢,我火速辦了婚禮凛澎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钮追。我一直安慰自己预厌,他們只是感情好阿迈,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布元媚。 她就那樣靜靜地躺著,像睡著了一般苗沧。 火紅的嫁衣襯著肌膚如雪刊棕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天待逞,我揣著相機(jī)與錄音甥角,去河邊找鬼。 笑死识樱,一個胖子當(dāng)著我的面吹牛嗤无,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播怜庸,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼当犯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了割疾?” 一聲冷哼從身側(cè)響起嚎卫,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宏榕,沒想到半個月后拓诸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侵佃,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年奠支,在試婚紗的時候發(fā)現(xiàn)自己被綠了馋辈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡倍谜,死狀恐怖首有,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情枢劝,我是刑警寧澤井联,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站您旁,受9級特大地震影響烙常,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹤盒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一蚕脏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侦锯,春花似錦驼鞭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亲桥,卻和暖如春洛心,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背题篷。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工词身, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人番枚。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓法严,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葫笼。 傳聞我的和親對象是個殘疾皇子深啤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容