HTML5 大檔上傳,使用 Resumable.js

嗯…其實這篇我是來打醬油的,本來要寫 demo code 發覺別人都寫好了哈哈,所以這邊單純做個指引而已

首先,HTML5 支援了一個檔案讀取的 API:FileReader,該 API 有個先決條件就是:你需要把檔案拖到瀏覽器內,或是 click 後選擇檔案,之後該 API 才有額外的東西可以動作

FileReader 提供了讀取檔案 raw data 的途徑,所以後來出現了一票類似線上轉檔改圖甚至類似 PhotoShop 的功能,因為有 raw data 後配上演算法基本上沒有啥做不出來的就是

先解釋一下運作原理:類似 Youtube 斷點上傳就是利用這功能,把檔案取得 raw data 後切成很多小的 chunk(其實就是小碎片)並把每個 chunk 編號,如果傳送失敗就把該 chunk 重新傳送即可,限制必須該頁沒有重新整理過(否則就是重新讀取,或是略過已經上傳過的 chunk 有點麻煩),而後來有人把這類的需求包裝後比較好用,就是這邊做為範例的 Resumable.js

github

官方網站

http://www.resumablejs.com/

所以有上面的基本解釋,你就會知道 Resumable.js 的 chunk 到底在設定啥鬼,類似 ChunkSize : 每塊大小,TotalSize : 可能為 chunk 總數或是檔案 max size,其實能設定的東西也不多就是了

而在這概念下其實就是把一個檔案拆成 N 個檔案上傳,所以『請自幹』,類似 paperclip 或是一般的 file upload 以 HTTP 而言都是單一檔案, Rails 內建也都不會幫你把多個檔案合併的,而 Resumable.js 的 sample 內其實給了一個很好的 for Rails 的指引

你其實可以看到都在自幹檔案合併就是(所以我可以偷懶不寫 code 了 X"D)不過這邊只補一個東西就是,它其實需要 authenticity_token 否則 Rails 會擋 Post 的 CSRF 的,所以文中最下也有 X-CSRF-Token 的加法,不過因為是 coffee script,我下面補充為一般的 JS 版本就是(尚未測試)

jQuery(function($){
  var r = new Resumable({
    target:'/api/photo/redeem-upload-token', 
    query:{upload_token:'my_token'},
    headers:{
      'X-CSRF-Token' : $('meta[name="csrf-token"]').attr('content')
    }
  });
  if(!r.support){
    console.log('not support!');
  }
});

大概就這樣而已唄,而如果你檔案上傳後要餵給類似 Paperclip / Carrierwave,你可以『上傳後』用類似的方式來進行

path = uploaded_file_path
#官方 demo code 可取得最後的 path,重新打開
file = File.open(path , 'a')
Item.create(
  :name => params['cute'],
  :file => file #取代掉類似params[:file]
)

原因是檔案上傳後的類似 params[:file].class 取得的應該都是 TempFile,該檔案存在 /tmp 下,而你可以自己開一個檔案丟進去,後續應該就會是相同效果就是了

另外給個進階議題,既然你都切 chunk 上傳了,則你可以顯示目前進度才是,看是要從 FileReader 或是從 Server 上面做都行,而另外一方面,其實 FileReader 支援多個檔案,所以這邊真的要做到非常完整的話,其實是可以支援多個檔案甚至是資料夾的,然後每個檔案依照單一檔案辦理即可

嗯,這主題大概就這些唄,以上

2個讚