文獻(xiàn)標(biāo)識(shí)碼: A
文章編號(hào): 0258-7998(2013)08-0137-03
在日常生活中,人們一直都在和數(shù)據(jù)信息打交道。數(shù)據(jù)信息組織和保存的方式很多,最常用的方式就是把數(shù)據(jù)信息保存在某種文件中,然后將文件上傳到FTP服務(wù)器[1]。但是當(dāng)用戶要對(duì)文件進(jìn)行操作時(shí),查找文件會(huì)顯得比較麻煩。本文提出通過數(shù)據(jù)庫直接記錄并管理這些文件中的數(shù)據(jù)信息[2],通過數(shù)據(jù)庫的SQL語句對(duì)相關(guān)的記錄進(jìn)行增刪查改,操作起來非常便捷,而且在數(shù)據(jù)庫中可以采用集群的技術(shù),為用戶提供高可靠性的服務(wù)?;?a class="innerlink" href="http://ihrv.cn/tags/Oracle數(shù)據(jù)庫" title="Oracle數(shù)據(jù)庫" target="_blank">Oracle數(shù)據(jù)庫的上傳下載軟件實(shí)現(xiàn)的主要功能是將一些文件寫入到數(shù)據(jù)庫,實(shí)現(xiàn)文件的上傳;然后再將數(shù)據(jù)庫中的內(nèi)容讀出,實(shí)現(xiàn)文件的下載。
本文設(shè)計(jì)不僅實(shí)現(xiàn)了文件的上傳和下載,還針對(duì)一些較大文件的上傳提出了一種分塊上傳的思想。先指定用戶想要的文件塊的大小,這個(gè)值決定了文件要被分割的塊數(shù),較大的文件分割成若干塊,每塊都以一條記錄的形式寫到數(shù)據(jù)庫中。當(dāng)某條記錄寫數(shù)據(jù)庫失敗時(shí),只需將那些寫數(shù)據(jù)庫失敗的文件塊重新上傳,不需要將整個(gè)文件重新上傳。采用這種方式可以提高文件上傳的效率,節(jié)約重新上傳時(shí)寫數(shù)據(jù)庫的時(shí)間。但下載時(shí),如果用戶需要完整的原始文件,原來屬于同一個(gè)文件的分塊則需要重新寫到一個(gè)文件中。本文使用邊下載、邊合并的方法,實(shí)現(xiàn)了分塊文件的合并下載。用戶可以根據(jù)自己的需要,針對(duì)性地下載其中的部分文件塊。讀取一個(gè)文件分塊相比讀一個(gè)完整的大文件要快很多,文件的分塊與合并提高了文件的上傳下載效率。值得注意的是,在設(shè)置文件分塊時(shí),分塊的大小要適度,否則會(huì)影響軟件的運(yùn)行效率[3],用戶可以根據(jù)實(shí)際要求設(shè)置文件分塊的大小。
1 大文件分塊上傳和下載軟件的實(shí)現(xiàn)
1.1 文件的分塊
將一個(gè)較大的文件上傳到數(shù)據(jù)庫時(shí),上傳速度往往會(huì)受到網(wǎng)絡(luò)寬帶的影響。針對(duì)較大文件的保存與管理,需對(duì)其進(jìn)行分塊,可以根據(jù)網(wǎng)絡(luò)的帶寬設(shè)置文件塊的大小,假設(shè)每個(gè)文件上傳的時(shí)間不超過5 s,設(shè)帶寬為k Mb/s,文件塊的大小BlockSize可以設(shè)置的范圍最好能夠滿足式(1):
(5×k/8)MB<BlockSize<(5×10×k/8)MB (1)
若文件塊的大小用BlockSize表示,則文件分成的塊數(shù)nCount與文件的大小之間的關(guān)系為:
nCount=Flength/BlockSize+1 (2)
K=Flength%BlockSize (3)
其中Flength代表原始文件的大小,K代表最后一個(gè)文件分塊的大小。因?yàn)槲募拇笮∨c文件塊的大小不一定剛好是整除的關(guān)系。最特殊的情況就是某文件的大小剛好小于文件塊的大小,此時(shí)的文件就只有一塊,即該文件本身。
1.2 分塊文件的上傳
將分塊文件上傳到數(shù)據(jù)庫之前,首先要在數(shù)據(jù)庫中創(chuàng)建一個(gè)存儲(chǔ)文件信息表,并定義相關(guān)的字段,方便用戶查詢和管理[4]。數(shù)據(jù)庫表中主要的相關(guān)字段包括:文件編號(hào)、文件名、文件大小、基本路徑、相對(duì)路徑、文件塊大小、文件塊編號(hào)、文件類型、文件內(nèi)容等。
文件上傳到數(shù)據(jù)庫主要步驟為:(1)將文件的名稱、路徑、大小、類型等基本信息寫入數(shù)據(jù)庫;(2)根據(jù)這些基本信息查找對(duì)應(yīng)的記錄,并將文件的內(nèi)容寫到blob字段中,文件內(nèi)容以二進(jìn)制的形式存貯在數(shù)據(jù)庫中[5-6]。
文件分塊上傳時(shí),首先連接服務(wù)器端的數(shù)據(jù)庫,在數(shù)據(jù)庫連接成功的條件下,遍歷要上傳的文件所在的路徑。當(dāng)查找到要上傳的文件時(shí),根據(jù)文件分塊的大小,計(jì)算文件分割的塊數(shù)和最后一個(gè)文件塊的大小,從第一個(gè)文件塊開始,計(jì)算過程如下:
(1) 判斷是否成功連接到數(shù)據(jù)庫。
(2) 判斷這是否為最后一個(gè)文件塊,如果是,則從文件中讀取最后一個(gè)文件塊,寫入數(shù)據(jù)庫后結(jié)束;否則從文件中讀取BlockSize個(gè)字節(jié)。
(3) 用Insert命令在對(duì)應(yīng)的表中寫入文件的編號(hào)、文件名稱、文件大小、文件的基本路徑及相對(duì)路徑、文件類型、文件塊的大小和編號(hào)。
(4) 通過文件編號(hào)、文件路徑,文件名稱和文件塊編號(hào)查找相應(yīng)的記錄。
(5) 將要寫入數(shù)據(jù)庫的文件內(nèi)容保存在一個(gè)安全數(shù)組中,并調(diào)用AppendChunk()函數(shù)將該塊文件內(nèi)容填到對(duì)應(yīng)的blob字段當(dāng)中,并更新記錄。
(6)為寫入記錄中的文件的路徑、文件名以及文件塊編號(hào)設(shè)置標(biāo)記,方便重新上傳時(shí)定位斷點(diǎn)的位置,跳轉(zhuǎn)到步驟(1)。
文件分塊上傳的流程圖如圖1所示。
如果服務(wù)器數(shù)據(jù)庫與客戶端的連接斷開,將導(dǎo)致文件上傳失敗。在客戶端與服務(wù)器端數(shù)據(jù)庫重新建立連接后,需要續(xù)傳文件,同時(shí)要通過斷開數(shù)據(jù)庫時(shí)的標(biāo)記,找到上次上傳文件的斷點(diǎn)。
續(xù)傳文件時(shí),為了找到文件續(xù)傳的起始位置,依然要遍歷文件所在的路徑,通過文件路徑和名稱找到對(duì)應(yīng)的文件,再使用文件塊的編號(hào)和文件塊的大小獲取下一次文件要上傳的位置。設(shè)offset為文件指針的偏移值,BlockNo為文件塊的編號(hào),BlockSize為文件塊的大小,三者之間的關(guān)系如下:
offset=BlockNo×BlockSize (4)
式中,被標(biāo)記文件塊的編號(hào)BlockNo乘以文件塊的大小BlockSize,就是續(xù)傳時(shí)讀取文件的偏移值。通過這個(gè)方法,就可以找到斷點(diǎn)所在的文件塊位置,實(shí)現(xiàn)文件的續(xù)傳, 從而避免重新上傳之前已經(jīng)寫入數(shù)據(jù)庫的文件塊。
1.3 分塊文件的下載
因?yàn)槲募潜4嬖跀?shù)據(jù)庫中的,用戶可用通過SQL命令對(duì)數(shù)據(jù)庫中的記錄進(jìn)行增刪查改等操作,這比存儲(chǔ)在FTP服務(wù)器中的文件處理要方便很多。下載的過程其實(shí)就是上傳的逆過程,思想相似。
下載時(shí)根據(jù)相關(guān)的查詢條件,如果存在符合條件的記錄,即可對(duì)這些記錄保存的文件進(jìn)行下載,在成功連接到數(shù)據(jù)庫的條件下,從第一條記錄開始執(zhí)行以下過程:
(1)判斷是否成功連接到數(shù)據(jù)庫。
(2)判斷該記錄是否超過最后一條記錄編號(hào),如果是,下載結(jié)束;否則跳轉(zhuǎn)到步驟(3)。
(3)從記錄中獲取文件的類型、文件名以及相對(duì)路徑,判斷該文件是否已經(jīng)存在,如果不存在,則根據(jù)文件的類型創(chuàng)建一個(gè)文件,以可追加的形式打開文件。
(4)調(diào)用GetChunk()函數(shù)獲取blob字段中的內(nèi)容,并保存在一個(gè)安全數(shù)組中,最后將安全數(shù)組中的數(shù)據(jù)寫入文件。
(5)關(guān)閉文件,并標(biāo)記該記錄中的文件路徑、文件名以及文件塊編號(hào),并跳轉(zhuǎn)到步驟(1)。
1.4 分塊文件的合并
本文雖然實(shí)現(xiàn)了文件的分塊下載,但是在實(shí)際情況中,人們通常希望使用完整的文件,而不是一個(gè)文件塊,所以在下載的過程中需要將各個(gè)文件的分塊重新合并成一個(gè)文件。本文采用的方法是在下載的過程中即可進(jìn)行合并操作,文件合并下載的流程圖如圖2所示。
文件的合并是文件合并下載過程中的一部分,即每次下載某條記錄中的文件內(nèi)容時(shí),先判斷該文件塊將寫入的文件。
用戶根據(jù)文件名稱,文件路徑等信息查找所需要的文件,如果存在符合條件的記錄,就依次訪問這些記錄,并將每條記錄中的文件內(nèi)容讀取出來,寫入相應(yīng)的文件中。從查詢到的第一條記錄開始:
(1)判斷是否已經(jīng)訪問了最后一條符合條件的記錄,如果是,則結(jié)束,否則轉(zhuǎn)到步驟(2)。
(2)獲取文件的路徑、文件名稱、文件類型等基本信息, 判斷當(dāng)前路徑下是否已經(jīng)存在這樣的文件,如果不存在,將創(chuàng)建一個(gè)對(duì)應(yīng)的文件;否則跳轉(zhuǎn)到步驟(3)。
(3)將記錄中的文件相對(duì)路徑、文件名兩個(gè)字段的內(nèi)容與上一條記錄中的相對(duì)路徑和文件名匹配,如果相同,則將文件內(nèi)容追加到該文件;否則根據(jù)該文件塊的基本信息重新創(chuàng)建一個(gè)文件。
(4)標(biāo)記該條記錄并移到下一條記錄,并跳轉(zhuǎn)到步驟(1)。
所有記錄被訪問完的同時(shí),所有的文件分塊都被寫入了相應(yīng)文件中,既不會(huì)出現(xiàn)文件內(nèi)容的覆蓋問題,也不會(huì)額外地占用存儲(chǔ)空間。
2 實(shí)驗(yàn)分析
通過測(cè)試發(fā)現(xiàn),文件的完整上傳所消耗的時(shí)間最短,但是上傳失敗后要重新上傳整個(gè)文件。如果使用文件的分塊上傳,文件分塊的大小要適當(dāng),分塊越多,上傳的速度就越慢。因?yàn)橛涗浢總€(gè)分塊文件的基本信息也要消耗一定的時(shí)間,在上傳失敗需要重新上傳的情況下,只需上傳剩下的沒有上傳成功的文件,效率有所提高。在下載的過程中,單塊文件明顯比整個(gè)文件的下載要快,因?yàn)閱螇K文件下載只需要讀取塊數(shù)據(jù)。而文件的合并下載時(shí)間比整塊文件下載時(shí)間要長(zhǎng),因?yàn)樵诤喜⒌倪^程中要判斷各個(gè)文件塊是否來源于同一個(gè)原始文件,會(huì)消耗一定的時(shí)間。
相對(duì)于普通的將文件上傳到FTP服務(wù)器,本文實(shí)現(xiàn)了基于Oracle數(shù)據(jù)庫的大文件分塊上傳下載應(yīng)用軟件,將文件的內(nèi)容以二進(jìn)制的形式分散保存在Oracle數(shù)據(jù)庫中,這不僅可以對(duì)大量數(shù)據(jù)信息進(jìn)行管理,還可以使得不同的用戶共享很多數(shù)據(jù)信息。文件的分塊上傳采用文件分割技術(shù),將文件分塊保存在數(shù)據(jù)庫中。通過文件的續(xù)傳,避免了由于各種網(wǎng)絡(luò)原因?qū)е碌膶憯?shù)據(jù)庫操作失敗,需要將整個(gè)文件重新上傳的問題。文件的合并下載解決了同一個(gè)文件中不同分塊的合并問題,避免了先下載文件再進(jìn)行合并的做法,提高了軟件的運(yùn)行效率。
參考文獻(xiàn)
[1] 馮素梅.基于FTP的文件上傳與下載研究[J].北京電力高等??茖W(xué)校學(xué)報(bào)(自然科學(xué)版),2010,27(5):197-199.
[2] 陶宏才.數(shù)據(jù)庫原理及設(shè)計(jì)[M]. 北京:清華大學(xué)出版社,2007.
[3] 張翼.BLOB數(shù)據(jù)優(yōu)化算法及其應(yīng)用[J].計(jì)算機(jī)測(cè)量與控制,2011(6):1478-1480.
[4] 徐孝凱,賀桂英.數(shù)據(jù)庫基礎(chǔ)與SQL Server應(yīng)用開發(fā)[M].北京:清華大學(xué)出版社,2008.
[5] 謝華成,張昆朋,范黎林,等.基于文件分割的二進(jìn)制大對(duì)象存取算法[J].計(jì)算機(jī)應(yīng)用,2011,31(10):2612-2616.
[6] 趙宇峰,張燁.VC存取數(shù)據(jù)庫的BLOB類型的方法[J].微型電腦應(yīng)用,2007,23(3):59-60.