文章目錄
目標
- 在上傳文件到linux系統時,某系統需要判斷一個文件是否已經上傳完成,那麼用什麼方法合適?
方法
判斷文件大小
- 這種方法對linux一般使用,但涉及到windows系統時,會出現問題
- 比如windows系統和linux系統使用共享存儲,因爲在windows系統移動、下載文件時,windows系統會使此文件屬性中的文件大小實際顯示爲實際大小,哪怕文件尚未傳輸完成
判斷文件的md5值
判斷整個文件的md5值
1. 發送端先計算好md5值,之後把md5值和文件一起傳輸過來
2. 接收端定時計算md5值,如果兩次或多次計算出的結果相同,則判斷已傳完
- 這種方法的弊端在於花費在計算md5的時間會偏長,而且需要開闢額外的空間去保存幾次計算出的md5值
判斷文件末尾幾位數
1. 判斷文件末尾幾位數(比如100位)是否完全一致,如果幾次的比較是一樣的,則認爲傳輸已完成
- 如果傳輸的視頻文件,又可能會出現問題,因爲一個視頻文件很可會存在大量空包,如果幾次取值正好取到空包,也會造成判斷失誤
判斷文件句柄
1. 通過判斷文件是否被佔用,如果解除了佔用則視爲文件已傳輸完成
- 這種方法在文件上傳到本地時非常好用,如果涉及到網絡存儲時,這種方式便不在適用
判斷最後修改時間
-
原理:文件上傳,或是移動,在動作結束後文件的最後修改時間modify time顯示的是實際文件內容發生變化的時間,而在上傳過程中,modify time隨內容的寫入實時地變化
-
請看下圖
[root@localhost 001]# stat \[0001\]特種兵之深入敵後30_“’\ (測試).ts
File: ‘[0001]特種兵之深入敵後30_“\’ (測試).ts’
Size: 2534512788 Blocks: 1163264 IO Block: 4096 regular file
Device: 805h/2053d Inode: 1612747302 Links: 1
Access: (0744/-rwxr--r--) Uid: ( 1000/ pukka01) Gid: ( 1000/ pukka01)
Access: 2019-06-19 11:48:37.480465258 +0800
Modify: 2019-06-19 11:49:02.107464688 +0800
Change: 2019-06-19 11:49:02.107464688 +0800
Birth: -
[root@localhost 001]# stat \[0001\]特種兵之深入敵後30_“’\ (測試).ts
File: ‘[0001]特種兵之深入敵後30_“\’ (測試).ts’
Size: 2534512788 Blocks: 1417216 IO Block: 4096 regular file
Device: 805h/2053d Inode: 1612747302 Links: 1
Access: (0744/-rwxr--r--) Uid: ( 1000/ pukka01) Gid: ( 1000/ pukka01)
Access: 2019-06-19 11:48:37.480465258 +0800
Modify: 2019-06-19 11:49:06.572464585 +0800
Change: 2019-06-19 11:49:06.572464585 +0800
Birth: -
[root@localhost 001]# stat \[0001\]特種兵之深入敵後30_“’\ (測試).ts
File: ‘[0001]特種兵之深入敵後30_“\’ (測試).ts’
Size: 2534512788 Blocks: 1449984 IO Block: 4096 regular file
Device: 805h/2053d Inode: 1612747302 Links: 1
Access: (0744/-rwxr--r--) Uid: ( 1000/ pukka01) Gid: ( 1000/ pukka01)
Access: 2019-06-19 11:48:37.480465258 +0800
Modify: 2019-06-19 11:49:08.402464542 +0800
Change: 2019-06-19 11:49:08.402464542 +0800
Birth: -
上圖爲一次傳輸過程中,隨機3次調用stat得到的圖
簡單分析下幾個相對重要的點:
- 文件於2019-06-19 11:48:37開始上傳
- 傳輸過程中Size始終不變
- 傳輸過程中Blocks始終在變
- 傳輸過程中由於Blocks始終在變,所以Change Time始終在變
- 傳輸過程中由於文件內容不斷地被修改,所以Modify Time始終在變
- 傳輸過程中Change Time和Modify Time始終相等(等於當前時間)
下圖爲傳輸結束後的圖
[root@localhost 001]# stat \[0001\]特種兵之深入敵後30_“’\ (測試).ts
File: ‘[0001]特種兵之深入敵後30_“\’ (測試).ts’
Size: 2534512788 Blocks: 4950224 IO Block: 4096 regular file
Device: 805h/2053d Inode: 1612747302 Links: 1
Access: (0744/-rwxr--r--) Uid: ( 1000/ pukka01) Gid: ( 1000/ pukka01)
Access: 2019-06-19 11:48:37.480465258 +0800
Modify: 2019-05-13 20:02:54.530000000 +0800
Change: 2019-06-19 11:50:13.389463037 +0800
Birth: -
簡單分析下幾個相對重要的點:
- 傳輸完成後Modify Time變回文件實際內容發生修改時間
根據傳輸過程中與傳輸結束後的對比,可以得到以下重要結論:
- 傳輸過程中Change Time與Modify Time始終相等(等於當前時間)
- 傳輸結束後Modify Time會變回文件傳輸前內容被修改的時間
- 傳輸過程中Blocks始終在變,結束後不再變化(不推薦用此特性來判斷文件是否上傳結束,因爲如果兩次掃描正好網絡中斷,則會導致誤判)
所以,根據以上結論可以得到至少兩種判斷文件是否傳輸完成的方法
方法1:判斷Modify Time與Change Time是否相等
- 如果不相等,則上傳成功
- 弊端1:一般情況下二者是相等的,特殊情況下就不一定了,比如高負載、高併發、網絡差、設備時鐘差等情況有可能會導致二者不相等,這便會導致誤判
- 弊端2:無法識別傳輸卡死與中斷
- 優點:快,識別速度取決與兩次掃描的間隔
方法2:判斷Modify Time與Change Time是否小於某個數
- 如果差值絕對值大於給定閥值,則視爲上傳成功
- 弊端1:假如文件的mtime與傳輸完成後的ctime本身就是十分接近,並小於給定閥值,(這是有可能的,比如文件生成後立刻傳輸,或兩臺設備存在時鐘差,或給定閥值過大),這就會導致識別失敗
- 弊端2:無法識別傳輸卡死與中斷
- 優點:相對上方案要穩,但對兩設備的時鐘有要求,對閥值數值要求嚴格
方法3:判斷Modify Time與當前時間差值絕對值
- 如果Modify Time與當前時間差值的絕對值大於閥值,則認爲傳輸完成
- 弊端1:具有一定的延時。因爲
- 兩臺設備可能有時間差
- 如果傳輸完成後文件本身的Modify Time與目的服務器的時間接近,便會帶來延遲
- 弊端2:無法識別傳輸卡死與中斷
- 優點:相對最穩
結論
- 本篇一共給出了三種判斷文件是否上傳的方法,具體採用哪種方法視環境所定