dropbox-api-petems 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -8
- data/README.markdown +21 -0
- data/dropbox-api.gemspec +10 -4
- data/lib/dropbox-api/client/files.rb +36 -0
- data/lib/dropbox-api/connection/requests.rb +4 -2
- data/lib/dropbox-api/version.rb +1 -1
- data/spec/lib/dropbox-api/client_spec.rb +40 -2
- data/spec/lib/dropbox-api/connection_spec.rb +2 -2
- metadata +95 -14
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -198,6 +198,27 @@ Stores a file with a provided body under a provided name and returns a Dropbox::
|
|
198
198
|
client.upload 'file.txt', 'file body' # => #<Dropbox::API::File>
|
199
199
|
```
|
200
200
|
|
201
|
+
### Dropbox::API::Client#chunked_upload
|
202
|
+
|
203
|
+
Stores a file using the chunked upload endpoint. This method issues multiple requests, and optionally takes a block, passing in the current upload byte offset and a unique ID usable for resuming uploads. Use this for uploading large files.
|
204
|
+
|
205
|
+
For more info, see [https://www.dropbox.com/developers/reference/api#chunked-upload](https://www.dropbox.com/developers/reference/api#chunked-upload)
|
206
|
+
|
207
|
+
Standard use:
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
client.chunked_upload 'file.txt', 'file or IO object' # => #<Dropbox::API::File>
|
211
|
+
```
|
212
|
+
|
213
|
+
Using a block to show upload progress and save the upload id:
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
client.chunked_upload 'file.txt', 'file or IO object' do |offset, resp|
|
217
|
+
@upload_id = resp[:upload_id]
|
218
|
+
puts "Uploaded #{offset} bytes"
|
219
|
+
end
|
220
|
+
```
|
221
|
+
|
201
222
|
### Dropbox::API::Client#download
|
202
223
|
|
203
224
|
Downloads a file with a provided name and returns it's content
|
data/dropbox-api.gemspec
CHANGED
@@ -9,13 +9,19 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["p.morsou@gmail.com"]
|
10
10
|
s.homepage = "http://github.com/petems/dropbox-api-petems"
|
11
11
|
s.summary = "A Ruby client for the DropBox REST API (Originally by marcinbunsch, forked by petems)"
|
12
|
-
s.description = "To deliver a more Rubyesque experience when using the DropBox API."
|
12
|
+
s.description = "To deliver a more Rubyesque experience when using the DropBox API (forked by petems)."
|
13
13
|
|
14
14
|
s.rubyforge_project = "dropbox-api"
|
15
15
|
|
16
|
-
s.add_dependency 'multi_json'
|
17
|
-
s.add_dependency 'oauth'
|
18
|
-
s.add_dependency 'hashie'
|
16
|
+
s.add_dependency 'multi_json', '1.7.9'
|
17
|
+
s.add_dependency 'oauth', '0.4.7'
|
18
|
+
s.add_dependency 'hashie', '2.0.5'
|
19
|
+
|
20
|
+
s.add_development_dependency 'rspec','2.14.1'
|
21
|
+
s.add_development_dependency 'rake', '10.1.0'
|
22
|
+
s.add_development_dependency 'simplecov', '0.7.1'
|
23
|
+
s.add_development_dependency 'ruby-debug19', '0.11.6'
|
24
|
+
s.add_development_dependency 'yajl-ruby', '1.1.0'
|
19
25
|
|
20
26
|
s.files = `git ls-files`.split("\n")
|
21
27
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -24,6 +24,42 @@ module Dropbox
|
|
24
24
|
Dropbox::API::File.init(response, self)
|
25
25
|
end
|
26
26
|
|
27
|
+
def chunked_upload(path, file, options = {})
|
28
|
+
root = options.delete(:root) || Dropbox::API::Config.mode
|
29
|
+
path = Dropbox::API::Util.escape(path)
|
30
|
+
upload_url = '/chunked_upload'
|
31
|
+
commit_url = ['', "commit_chunked_upload", root, path].compact.join('/')
|
32
|
+
|
33
|
+
total_file_size = ::File.size(file)
|
34
|
+
chunk_size = options[:chunk_size] || 4*1024*1024 # default 4 MB chunk size
|
35
|
+
offset = options[:offset] || 0
|
36
|
+
upload_id = options[:upload_id]
|
37
|
+
|
38
|
+
while offset < total_file_size
|
39
|
+
data = file.read(chunk_size)
|
40
|
+
|
41
|
+
query = Dropbox::API::Util.query(options.merge(:offset => offset))
|
42
|
+
response = connection.put(:content, "#{upload_url}?#{query}", data, {
|
43
|
+
'Content-Type' => "application/octet-stream",
|
44
|
+
"Content-Length" => data.length.to_s
|
45
|
+
})
|
46
|
+
|
47
|
+
upload = Dropbox::API::Object.init(response, self)
|
48
|
+
options[:upload_id] ||= upload[:upload_id]
|
49
|
+
offset += upload[:offset].to_i - offset if upload[:offset] && upload[:offset].to_i > offset
|
50
|
+
yield offset, upload if block_given?
|
51
|
+
end
|
52
|
+
|
53
|
+
query = Dropbox::API::Util.query({:upload_id => options[:upload_id]})
|
54
|
+
|
55
|
+
response = connection.post(:content, "#{commit_url}?#{query}", "", {
|
56
|
+
'Content-Type' => "application/octet-stream",
|
57
|
+
"Content-Length" => "0"
|
58
|
+
})
|
59
|
+
|
60
|
+
Dropbox::API::File.init(response, self)
|
61
|
+
end
|
62
|
+
|
27
63
|
def copy_from_copy_ref(copy_ref, to, options = {})
|
28
64
|
raw.copy({
|
29
65
|
:from_copy_ref => copy_ref,
|
@@ -32,10 +32,12 @@ module Dropbox
|
|
32
32
|
raise Dropbox::API::Error::Redirect.new("#{status} - Redirect Error")
|
33
33
|
when 503
|
34
34
|
parsed = MultiJson.decode(response.body)
|
35
|
-
|
35
|
+
header_parse = MultiJson.decode(response.headers)
|
36
|
+
error_message = "#{parsed["error"]}. Retry after: #{header_parse['Retry-After']}"
|
37
|
+
raise Dropbox::API::Error.new("503 - #{error_message}")
|
36
38
|
when 507
|
37
39
|
raise Dropbox::API::Error::StorageQuota.new("507 - Dropbox storage quota exceeded.")
|
38
|
-
when 500..599
|
40
|
+
when 500..502, 504..506, 508..599
|
39
41
|
parsed = MultiJson.decode(response.body)
|
40
42
|
raise Dropbox::API::Error.new("#{status} - Server error. Check http://status.dropbox.com/")
|
41
43
|
else
|
data/lib/dropbox-api/version.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "spec_helper"
|
3
|
+
require "tempfile"
|
3
4
|
|
4
5
|
describe Dropbox::API::Client do
|
5
6
|
|
@@ -114,6 +115,43 @@ describe Dropbox::API::Client do
|
|
114
115
|
end
|
115
116
|
end
|
116
117
|
|
118
|
+
describe "#chunked_upload" do
|
119
|
+
|
120
|
+
before do
|
121
|
+
@filename = "/tmp/dropbox-api-largefile-test"
|
122
|
+
@size = 5*1024*1024 # 5MB, to test the 4MB chunk size
|
123
|
+
@file = File.open(@filename, "w") {|f| f.write "a"*@size}
|
124
|
+
end
|
125
|
+
|
126
|
+
it "puts a 5MB file in dropbox" do
|
127
|
+
filename = "#{Dropbox::Spec.test_dir}/test-5MB-#{Dropbox::Spec.namespace}.txt"
|
128
|
+
response = @client.chunked_upload filename, File.open(@filename)
|
129
|
+
response.path.should == filename
|
130
|
+
response.bytes.should == @size
|
131
|
+
end
|
132
|
+
|
133
|
+
it "yields current offset and upload id" do
|
134
|
+
filename = "#{Dropbox::Spec.test_dir}/test-yield-#{Dropbox::Spec.namespace}.txt"
|
135
|
+
log_offset = ""
|
136
|
+
log_upload = ""
|
137
|
+
response = @client.chunked_upload filename, File.open(@filename) do |offset, upload|
|
138
|
+
offset.should be > 0
|
139
|
+
log_offset += "#{offset.to_s},"
|
140
|
+
log_upload += upload.inspect
|
141
|
+
upload[:upload_id].length.should eq(22)
|
142
|
+
end
|
143
|
+
response.path.should == filename
|
144
|
+
response.bytes.should == @size
|
145
|
+
log_offset.should match(/[\d]{7},[\d]{7},/)
|
146
|
+
log_upload.should include("Dropbox::API::Object","upload_id=")
|
147
|
+
end
|
148
|
+
|
149
|
+
after do
|
150
|
+
FileUtils.rm @filename
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
117
155
|
describe "#search" do
|
118
156
|
|
119
157
|
let(:term) { "searchable-test-#{Dropbox::Spec.namespace}" }
|
@@ -143,10 +181,10 @@ describe Dropbox::API::Client do
|
|
143
181
|
it "copies a file from a copy_ref" do
|
144
182
|
filename = "test/searchable-test-#{Dropbox::Spec.namespace}.txt"
|
145
183
|
@client.upload filename, "Some file"
|
146
|
-
response = @client.search "searchable-test-#{Dropbox::Spec.namespace}", :path => 'test'
|
184
|
+
response = @client.search "searchable-test-#{Dropbox::Spec.namespace}", :path => 'test'
|
147
185
|
ref = response.first.copy_ref['copy_ref']
|
148
186
|
@client.copy_from_copy_ref ref, "#{filename}.copied"
|
149
|
-
response = @client.search "searchable-test-#{Dropbox::Spec.namespace}.txt.copied", :path => 'test'
|
187
|
+
response = @client.search "searchable-test-#{Dropbox::Spec.namespace}.txt.copied", :path => 'test'
|
150
188
|
response.size.should == 1
|
151
189
|
response.first.class.should == Dropbox::API::File
|
152
190
|
end
|
@@ -79,10 +79,10 @@ describe Dropbox::API::Connection do
|
|
79
79
|
end
|
80
80
|
|
81
81
|
it "raises a Dropbox::API::Error when the response is a 503" do
|
82
|
-
response = double :code => 503, :body => '{ "error": "rate limited" }'
|
82
|
+
response = double :code => 503, :body => '{ "error": "rate limited" }', :headers => '{ "Retry-After": "50" }'
|
83
83
|
lambda do
|
84
84
|
@connection.request { response }
|
85
|
-
end.should raise_error(Dropbox::API::Error, '503 -
|
85
|
+
end.should raise_error(Dropbox::API::Error, '503 - rate limited. Retry after: 50')
|
86
86
|
end
|
87
87
|
|
88
88
|
it "raises a Dropbox::API::Error::StorageQuota when the response is a 507" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dropbox-api-petems
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -16,50 +16,131 @@ dependencies:
|
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 1.7.9
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 1.7.9
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: oauth
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - '='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 0.4.7
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - '='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 0.4.7
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: hashie
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - '='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
53
|
+
version: 2.0.5
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
62
|
-
|
61
|
+
version: 2.0.5
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - '='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.14.1
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.14.1
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - '='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 10.1.0
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - '='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 10.1.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: simplecov
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - '='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 0.7.1
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - '='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.7.1
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: ruby-debug19
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.11.6
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - '='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.11.6
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: yajl-ruby
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - '='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 1.1.0
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - '='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 1.1.0
|
142
|
+
description: To deliver a more Rubyesque experience when using the DropBox API (forked
|
143
|
+
by petems).
|
63
144
|
email:
|
64
145
|
- p.morsou@gmail.com
|
65
146
|
executables: []
|