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 CHANGED
@@ -1,10 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in dropbox-api.gemspec
4
- gemspec
5
-
6
- gem "rspec"
7
- gem "rake"
8
- gem 'simplecov'
9
- gem "ruby-debug19"
10
- gem "yajl-ruby"
4
+ gemspec
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
- raise Dropbox::API::Error.new("503 - Possible Rate Limiting: #{parsed["error"]}")
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
@@ -1,5 +1,5 @@
1
1
  module Dropbox
2
2
  module API
3
- VERSION = "0.4.1"
3
+ VERSION = "0.4.2"
4
4
  end
5
5
  end
@@ -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 - Possible Rate Limiting: rate limited')
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.1
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: '0'
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: '0'
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: '0'
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: '0'
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: '0'
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: '0'
62
- description: To deliver a more Rubyesque experience when using the DropBox API.
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: []