大文件斷點(diǎn)續(xù)傳如何實(shí)現(xiàn)?
最近接到一個(gè)新的需求,需要上傳2G
左右的視頻文件,用測試環(huán)境的OSS
試了一下,上傳需要十幾分鐘,再考慮到公司的資源問題,果斷放棄該方案。
一提到大文件上傳,我最先想到的就是各種網(wǎng)盤了,現(xiàn)在大家都喜歡將自己收藏的「小電影」上傳到網(wǎng)盤進(jìn)行保存。網(wǎng)盤一般都支持?jǐn)帱c(diǎn)續(xù)傳和文件秒傳功能,減少了網(wǎng)絡(luò)波動(dòng)和網(wǎng)絡(luò)帶寬對(duì)文件的限制,大大提高了用戶體驗(yàn),讓人愛不釋手。
說到這,大家先來了解一下這幾個(gè)概念:
「文件分塊」:將大文件拆分成小文件,將小文件上傳\下載,最后再將小文件組裝成大文件;
「斷點(diǎn)續(xù)傳」:在文件分塊的基礎(chǔ)上,將每個(gè)小文件采用單獨(dú)的線程進(jìn)行上傳\下載,如果碰到網(wǎng)絡(luò)故障,可以從已經(jīng)上傳\下載的部分開始繼續(xù)上傳\下載未完成的部分,而沒有必要從頭開始上傳\下載;
「文件秒傳」:資源服務(wù)器中已經(jīng)存在該文件,其他人上傳時(shí)直接返回該文件的URI。
RandomAccessFile
平時(shí)我們都會(huì)使用FileInputStream
,FileOutputStream
,FileReader
以及FileWriter
等IO
流來讀取文件,今天我們來了解一下RandomAccessFile
。
它是一個(gè)直接繼承Object
的獨(dú)立的類,底層實(shí)現(xiàn)中它實(shí)現(xiàn)的是DataInput
和DataOutput
接口。該類支持隨機(jī)讀取文件,隨機(jī)訪問文件類似于文件系統(tǒng)中存儲(chǔ)的大字節(jié)數(shù)組。
它的實(shí)現(xiàn)基于「文件指針」(一種游標(biāo)或者指向隱含數(shù)組的索引),文件指針可以通過getFilePointer
方法讀取,也可以通過seek
方法設(shè)置。
輸入時(shí)從文件指針開始讀取字節(jié),并使文件指針超過讀取的字節(jié),如果寫入超過隱含數(shù)組當(dāng)前結(jié)尾的輸出操作會(huì)導(dǎo)致擴(kuò)展數(shù)組。該類有四種模式可供選擇:
r: 以只讀方式打開文件,如果執(zhí)行寫入操作會(huì)拋出
IOException
;rw: 以讀、寫方式打開文件,如果文件不存在,則嘗試創(chuàng)建文件;
rws: 以讀、寫方式打開文件,要求對(duì)文件內(nèi)容或元數(shù)據(jù)的每次更新都同步寫入底層存儲(chǔ)設(shè)備;
rwd: 以讀、寫方式打開文件,要求對(duì)文件內(nèi)容的每次更新都同步寫入底層存儲(chǔ)設(shè)備;
在rw
模式下,默認(rèn)是使用buffer
的,只有cache
滿的或者使用RandomAccessFile.close()
關(guān)閉流的時(shí)候才真正的寫到文件。
API
1、void seek(long pos)
:設(shè)置下一次讀取或?qū)懭霑r(shí)的文件指針偏移量,通俗點(diǎn)說就是指定下次讀文件數(shù)據(jù)的位置。
?偏移量可以設(shè)置在文件末尾之外,只有在偏移量設(shè)置超出文件末尾后,才能通過寫入更改文件長度;
?
2、native long getFilePointer()
:返回當(dāng)前文件的光標(biāo)位置;
3、native long length()
:返回當(dāng)前文件的長度;
4、「讀」方法

5、「寫」方法

6、readFully(byte[] b)
:這個(gè)方法的作用就是將文本中的內(nèi)容填滿這個(gè)緩沖區(qū)b。如果緩沖b不能被填滿,那么讀取流的過程將被阻塞,如果發(fā)現(xiàn)是流的結(jié)尾,那么會(huì)拋出異常;
7、FileChannel getChannel()
:返回與此文件關(guān)聯(lián)的唯一FileChannel
對(duì)象;
8、int skipBytes(int n)
:試圖跳過n個(gè)字節(jié)的輸入,丟棄跳過的字節(jié);
??
RandomAccessFile
的絕大多數(shù)功能,已經(jīng)被JDK1.4
的NIO的「內(nèi)存映射」文件取代了,即把文件映射到內(nèi)存后再操作,省去了頻繁磁盤io
。