大文件上傳解決方案與實例代碼

核心:

  • 分段接收,分段解析,分段寫文件

問題

  • Q:不同用戶上傳同一文件:

    • A: 通過token加文件md5碼解決,並且後期如果發現爲同一文件甚至不需要上傳,直接服務器cp一份
  • Q:同一個用戶刷新上傳(重複上傳)

    • A:通過會話id (processId: 通過token+md5 生成,防止上傳重複上傳同一文件,碎片共享同一個processId) & 碎片狀態化: 杜絕重複上傳碎片,同時實現斷點續傳
      • Q: 爲什麼要token+md5
        • A: 可以防止如下
          • md5作用:防止A用戶重複上傳同一文件"
          • 防止A用戶重複上傳同一文件"
          • 防止A用戶重複上傳同一文件"
          • token:防止A用戶上傳的碎片 跑到B碎片上 (既A,B上傳類似碎片或者同一視頻)
      • Q: 碎片有哪些狀態:
        • A: 傳輸失敗 | 正在傳輸(因爲是分段解析,所以會有中間狀態) | 傳輸成功
      • Q: 碎片共享同一個processId會出現數據冗餘嗎:
        • A: 不會,processId並非uuid,只要是同一個文件以及同一個用戶,必然相同
    • Q: processId誰頒發:
      • A: 前端頒發 | 後端頒發 ,延伸問題請看 進度條查詢部分
  • Q: 進度條如何查詢:

    • Q: 碎片進度查詢:
      • A: 碎片有index(chunk)塊的概念,緩存中存放了該碎片的總的容量,以及已經緩存的容量
        • Q: 需要攜帶的參數:
          • A: 文件的md5(非碎片的md5,在本處無碎片md5的概念) & 碎片的chunk (代表第幾塊)
            • 切片還是需要攜帶MD5,並且是自身的md5,因爲 processId和chunk 並不能代表這個chunk,md5可以
            • Q: 如果 會話id是由服務器頒發 何時發起輪詢請求:
              • A: 完美的方式是當服務端收到請求之後通過webSocket通知前端 你收到本次會話的id了,發起輪詢吧 若不採用websocket,則只能前端攜帶uuid給後端後,後端存儲k-v(key爲uuid,value爲會話id),前端通過uuid輪詢服務器獲取會話id ,所以 會話id還不如前端頒發
    • Q: 文件進度查詢:
      • A: 已上傳的部分累加 / 總數
    • Q: 碎片進度如何更新: 通過BufferedInputStream 分段讀取每次請求的數據,之後更新到緩存中 (既 分段解析)
  • Q: 何時合併文件,既何時結束

    • A: 前端發起通知,後端開始合併碎片
      • Q: 能否後端主動發起合併: 本項目中自己自動合併
        • A: 可以,但是必須額外傳遞一個 總碎片數參數
          • 單文件形式: ,後端判斷是否是最後一塊
          • 多文件形式: 額外定義一個原子變量(可以優化到redis中)做累加,達到數目開啓合併 ,但是必須要確保數據讀取正確,不能有bab的問題,redis可以實現
    • Q: 如何合併,全部讀取再加載到內存中?
      • WIP A: Java 暫時通過FileChannel實現
  • Q: 如何斷點續傳:

    • A: 服務端存儲切片的唯一信息,寫入的時候判斷是否存在即可
  • Q: 如何分段寫入到文件:

    • 通過randAccessFile
  • Q: 在上傳途中,服務器宕機怎麼辦,確切點說既緩存碎片狀態的服務器掛了,數據清空了(保存在內存中)

    • A: 既: 如果MD5等信息是存儲在內存中,而磁盤碎片是存在的
      • 要麼是傳輸中途斷了,既失敗了同時緩存也丟了-> 刪除|清空
      • 要麼是傳輸成功了,但是緩存丟了-> 依舊刪除
      • 所以,緩存丟了就刪除
  • Q: 當合並的時候,合併失敗:

對象:

上傳對象

  • chunk: 代表碎片下標

Talk is cheap , I am coding

  • DEMO
    • 更改文件名即可,支持進度展示,不需要sql,nosql
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章