如何判斷文件已上傳

目標

  • 在上傳文件到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得到的圖
簡單分析下幾個相對重要的點:

  1. 文件於2019-06-19 11:48:37開始上傳
  2. 傳輸過程中Size始終不變
  3. 傳輸過程中Blocks始終在變
  4. 傳輸過程中由於Blocks始終在變,所以Change Time始終在變
  5. 傳輸過程中由於文件內容不斷地被修改,所以Modify Time始終在變
  6. 傳輸過程中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: -

簡單分析下幾個相對重要的點:

  1. 傳輸完成後Modify Time變回文件實際內容發生修改時間

根據傳輸過程中與傳輸結束後的對比,可以得到以下重要結論:

  1. 傳輸過程中Change Time與Modify Time始終相等(等於當前時間)
  2. 傳輸結束後Modify Time會變回文件傳輸前內容被修改的時間
  3. 傳輸過程中Blocks始終在變,結束後不再變化(不推薦用此特性來判斷文件是否上傳結束,因爲如果兩次掃描正好網絡中斷,則會導致誤判)

所以,根據以上結論可以得到至少兩種判斷文件是否傳輸完成的方法

方法1:判斷Modify Time與Change Time是否相等
  1. 如果不相等,則上傳成功
  2. 弊端1:一般情況下二者是相等的,特殊情況下就不一定了,比如高負載、高併發、網絡差、設備時鐘差等情況有可能會導致二者不相等,這便會導致誤判
  3. 弊端2:無法識別傳輸卡死與中斷
  4. 優點:快,識別速度取決與兩次掃描的間隔
方法2:判斷Modify Time與Change Time是否小於某個數
  1. 如果差值絕對值大於給定閥值,則視爲上傳成功
  2. 弊端1:假如文件的mtime與傳輸完成後的ctime本身就是十分接近,並小於給定閥值,(這是有可能的,比如文件生成後立刻傳輸,或兩臺設備存在時鐘差,或給定閥值過大),這就會導致識別失敗
  3. 弊端2:無法識別傳輸卡死與中斷
  4. 優點:相對上方案要穩,但對兩設備的時鐘有要求,對閥值數值要求嚴格
方法3:判斷Modify Time與當前時間差值絕對值
  1. 如果Modify Time與當前時間差值的絕對值大於閥值,則認爲傳輸完成
  2. 弊端1:具有一定的延時。因爲
    1. 兩臺設備可能有時間差
    2. 如果傳輸完成後文件本身的Modify Time與目的服務器的時間接近,便會帶來延遲
  3. 弊端2:無法識別傳輸卡死與中斷
  4. 優點:相對最穩

結論

  1. 本篇一共給出了三種判斷文件是否上傳的方法,具體採用哪種方法視環境所定
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章