記事の要約
-
DropboxClient::ChunkedUploader#upload
はエラーが発生するまでアップロードし続ける仕様 - でもそれだとアップロード時の進捗把握が困難
- uploadを呼ぶ度にチャンクサイズ分だけアップロードしてすぐreturnしたい
- そんなパッチを作った
DropboxClient::ChunkedUploader#uploadの仕様
きっかけはRuby Dropbox SDK 1.6.1のDropboxClient::ChunkedUploader#upload
メソッドの挙動を誤解していたことです。
私は勝手にチャンクサイズ分だけアップロードしてreturnするメソッドだと思い込んでいたのですが、RDoc Documentationを読みなおしたところ、
upload(chunk_size=4*1024*1024)
Uploads data from this ChunkedUploader’s file_obj in chunks, until an error occurs.
と書いてありました。
つまり、チャンクサイズ分だけアップロードしてreturnするのではなく、
エラーが発生するまで何度もチャンクサイズ分のアップロードを繰り返します。
でもこれだとアップロードの進捗を把握できないじゃないですか!なんて不便な!
私のやりたいことを実現できるメソッドがないかなーと思いつつDocumentationを眺めていたところ、
#partial_chunked_upload — DropboxClientなるものを発見しました。
これを使えばぼくのかんがえたさいきょうのupload
メソッドを実装できそう!
そんなわけで作っちゃいました。
パッチ
今回書いたコードがこちらです。
実装にあたっては、https://github.com/ntamvl/rbackup/blob/66982530dbedf1c9d26713274910fa67c4d4b96f/lib/backup/storage/dropbox.rb を参考にさせていただきました。
# dropbox sdk 1.6.1 のチャンクアップロードを
# 1回アップロードするごとにreturnさせるパッチ
class DropboxClient
class ChunkedUploader
def upload(chunk_size = 1024**2 * 4)
@file_obj.seek(@offset) unless @file_obj.pos == @offset
data = @file_obj.read chunk_size
begin
response = @client.partial_chunked_upload data, @upload_id, @offset
rescue => e
response = JSON.parse(e.http_response) rescue {}
raise e unless response.body['offset']
end
metadata = JSON.parse response.body
@upload_id = metadata['upload_id']
@offset = metadata['offset'].to_i
end
end
end
使い方
こんな感じでアップロードの進捗を把握できます。
dropbox = DropboxClient.new DROPBOX_ACCESS_TOKEN
chunked_uploader = dropbox.get_chunked_uploader file_obj, file_obj.size
while chunked_uploader.offset < file_obj.size do
chunked_uploader.upload # 既定のチャンクサイズ(4MB)分だけアップロード
progress = 100 * chunked_uploader.offset / file_obj.size # 進捗(%)
end
chunked_uploader.finish to_path
まとめ
Ruby Dropbox SDK 1.6.1のチャンクアップローダを改良し、ファイルアップロード時の進捗把握を容易にしました。
参考
RDoc Documentation - https://www.dropboxstatic.com/static/developers/dropbox-ruby-sdk-1.6.1-docs/index.html
rbackup/dropbox.rb at 66982530dbedf1c9d26713274910fa67c4d4b96f · ntamvl/rbackup - https://github.com/ntamvl/rbackup/blob/66982530dbedf1c9d26713274910fa67c4d4b96f/lib/backup/storage/dropbox.rb