dropbox_api
dropbox_api copied to clipboard
Chunked downloads
For getting large files from a user's Dropbox, their API allows you to specify a range of bytes--is this possible in the current dropbox_api
gem's DSL?
Sorry for the late reply.
I couldn't find the option to download a specific range of bytes anywhere in their API documentation. Could you link to any resource related to this?
If this is actually possible I'd be interested in implementing this feature.
https://www.dropbox.com/developers-v1/core/docs#files-GET Look at the Notes section
That link is for Dropbox API v1, this library implements API v2.
However, I could find this in the docs from v2:
As with content-upload endpoints, arguments are passed in the Dropbox-API-Arg request header or arg URL parameter. The response body contains file content, so the result will appear as JSON in the Dropbox-API-Result response header. These endpoints are also on the content.dropboxapi.com domain. These endpoints also support HTTP GET along with ETag-based caching (If-None-Match) and HTTP range requests.
Source: https://www.dropbox.com/developers/documentation/http/documentation#formats
So, you're right and it should be possible to download a range of bytes. I'm not sure yet about the details on how this is meant to work.
I'll see if we can have support for this feature soon.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
Here's my monkeypatch:
module DropboxApi::Endpoints
class Base
def process_response(raw_response)
# Official Dropbox documentation for HTTP error codes:
# https://www.dropbox.com/developers/documentation/http/documentation#error-handling
case raw_response.status
when 200, 206, 409
# Status code 409 is "Endpoint-specific error". We need to look at
# the response body to build an exception.
build_result(raw_response.env[:api_result])
when 429
error = DropboxApi::Errors::TooManyRequestsError.build(
raw_response.env[:api_result]["error_summary"],
raw_response.env[:api_result]["error"]["reason"]
)
error.retry_after = raw_response.headers["retry-after"].to_i
raise error
else
raise DropboxApi::Errors::HttpError,
"HTTP #{raw_response.status}: #{raw_response.body}"
end
end
end
class ContentChunkedDownload < DropboxApi::Endpoints::Base
def initialize(builder)
@connection = builder.build("https://content.dropboxapi.com") do |c|
c.response :decode_result
end
end
def build_request(params)
body = nil
range_from = params.delete(:range_from)
range_to = params.delete(:range_to)
range = "bytes=#{range_from}-#{range_to}" unless range_from.nil? || range_from.nil?
headers = {
'Dropbox-API-Arg' => JSON.dump(params),
'Content-Type' => ''
}
headers.merge!({ 'Range' => range }) unless range.nil?
return body, headers
end
def perform_request(params)
response = get_response(params)
api_result = process_response response
# TODO: Stream response, current implementation will fail with very large
# files.
yield response.body if block_given?
api_result
end
end
end
module DropboxApi::Endpoints::Files
class DownloadChunked < DropboxApi::Endpoints::ContentChunkedDownload
Method = :post
Path = "/2/files/download".freeze
ResultType = DropboxApi::Metadata::File
ErrorType = DropboxApi::Errors::DownloadError
# Download a file from a users Dropbox.
#
# @param path [String] The path of the file to download.
add_endpoint :download_chunk do |path, from, to, &block|
perform_request({:path => path}.merge(range_from: from, range_to: to), &block)
end
end
end