s3_multipart 0.0.10.5 → 0.0.10.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d98ae2406219c5a736d33bf323dfb675f2649e18
4
- data.tar.gz: 790a0d7b0d2d42765c05474851eaffd773845a10
3
+ metadata.gz: e74a7aee76d8f60af7b749993e1257c1392f3324
4
+ data.tar.gz: b89221f39db1562e39906af3ede3c3b589789489
5
5
  SHA512:
6
- metadata.gz: c5aec821b693decc4f4d86a4ef4a7fa000dfe3e3a051dc7567c42de585da0a97d466d7193b9b68cfec34e88f40ef62149959f9cacd7ea3b594bf39ad9b093c13
7
- data.tar.gz: 3885d74fa41187e425cd4273d73bad593221937368efa238592efa5a31c24b2f781e479db623af403f4c97c940fed06335a2060151bf3a0e72f09a987bfcacfc
6
+ metadata.gz: ccd1414d670078a844ee5a3aa18499c318fec1a54e6e5b834d0b2dd7e55ac966ac7df4a5108e6dc879e937755d55642ca939c76e6fd7608919eadd6150939228
7
+ data.tar.gz: 86f8560e32863f0534adf0fd5681321ba48885affe480f98fa031491d272770591d3c83694a29abc7ab0c2e98adf750837e430777d331a2413398d3cb97d0de9
data/.gitignore CHANGED
@@ -18,3 +18,7 @@ _SpecRunner.html
18
18
 
19
19
  *.swp
20
20
  *.swo
21
+
22
+ .ruby-version
23
+ .rbenv-gemset
24
+ .rbenv-gemsets
data/Gemfile CHANGED
@@ -2,18 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  group :development do
4
4
  gem 'activerecord'
5
- gem 'sqlite3'
6
5
  gem 'actionpack' # action_controller, action_view
7
6
  gem 'sprockets'
8
- gem "rails"
9
- gem "sqlite3"
10
-
11
- # tests
12
- gem 'combustion', '~> 0.3.3'
13
- gem 'rspec'
14
- gem 'rspec-rails'
15
- gem 'capybara'
16
- # gem 'jasmine'
17
7
 
18
8
  # assets
19
9
  gem 'sass-rails', '~> 3.2.3'
@@ -23,4 +13,4 @@ group :development do
23
13
 
24
14
  gemspec
25
15
 
26
- end
16
+ end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- s3_multipart (0.0.10.4)
4
+ s3_multipart (0.0.10.5)
5
5
  uuid (>= 2.3.6)
6
6
  xml-simple (>= 1.1.2)
7
7
 
@@ -64,7 +64,7 @@ GEM
64
64
  sass (~> 3.1)
65
65
  compass-rails (1.0.3)
66
66
  compass (>= 0.12.2, < 0.14)
67
- diff-lcs (1.1.3)
67
+ diff-lcs (1.2.5)
68
68
  erubis (2.7.0)
69
69
  execjs (1.4.0)
70
70
  multi_json (~> 1.0)
@@ -83,8 +83,8 @@ GEM
83
83
  libwebsocket (0.1.7.1)
84
84
  addressable
85
85
  websocket
86
- macaddr (1.6.1)
87
- systemu (~> 2.5.0)
86
+ macaddr (1.7.1)
87
+ systemu (~> 2.6.2)
88
88
  mail (2.4.4)
89
89
  i18n (>= 0.4.0)
90
90
  mime-types (~> 1.16)
@@ -118,21 +118,18 @@ GEM
118
118
  rake (10.0.3)
119
119
  rdoc (3.12)
120
120
  json (~> 1.4)
121
- rspec (2.12.0)
122
- rspec-core (~> 2.12.0)
123
- rspec-expectations (~> 2.12.0)
124
- rspec-mocks (~> 2.12.0)
125
- rspec-core (2.12.2)
126
- rspec-expectations (2.12.1)
127
- diff-lcs (~> 1.1.3)
128
- rspec-mocks (2.12.1)
129
- rspec-rails (2.12.0)
121
+ rspec-core (2.14.8)
122
+ rspec-expectations (2.14.5)
123
+ diff-lcs (>= 1.1.3, < 2.0)
124
+ rspec-mocks (2.14.6)
125
+ rspec-rails (2.14.2)
130
126
  actionpack (>= 3.0)
127
+ activemodel (>= 3.0)
131
128
  activesupport (>= 3.0)
132
129
  railties (>= 3.0)
133
- rspec-core (~> 2.12.0)
134
- rspec-expectations (~> 2.12.0)
135
- rspec-mocks (~> 2.12.0)
130
+ rspec-core (~> 2.14.0)
131
+ rspec-expectations (~> 2.14.0)
132
+ rspec-mocks (~> 2.14.0)
136
133
  rubyzip (0.9.9)
137
134
  sass (3.2.3)
138
135
  sass-rails (3.2.5)
@@ -150,17 +147,17 @@ GEM
150
147
  rack (~> 1.0)
151
148
  tilt (~> 1.1, != 1.3.0)
152
149
  sqlite3 (1.3.6)
153
- systemu (2.5.2)
150
+ systemu (2.6.4)
154
151
  thor (0.16.0)
155
152
  tilt (1.3.3)
156
153
  treetop (1.4.12)
157
154
  polyglot
158
155
  polyglot (>= 0.3.1)
159
156
  tzinfo (0.3.35)
160
- uuid (2.3.6)
157
+ uuid (2.3.7)
161
158
  macaddr (~> 1.0)
162
159
  websocket (1.0.6)
163
- xml-simple (1.1.2)
160
+ xml-simple (1.1.3)
164
161
  xpath (1.0.0)
165
162
  nokogiri (~> 1.3)
166
163
 
@@ -176,8 +173,7 @@ DEPENDENCIES
176
173
  compass-rails
177
174
  jquery-ui-rails
178
175
  rails
179
- rspec
180
- rspec-rails
176
+ rspec-rails (~> 2.14, >= 2.14.2)
181
177
  s3_multipart!
182
178
  sass-rails (~> 3.2.3)
183
179
  sprockets
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # S3 Multipart
2
+ [![Gem Version](https://badge.fury.io/rb/s3_multipart.svg)](http://badge.fury.io/rb/s3_multipart)
2
3
 
3
4
  The S3 Multipart gem brings direct multipart uploading to S3 to Rails. Data is piped from the client straight to Amazon S3 and a server-side callback is run when the upload is complete.
4
5
 
@@ -6,6 +7,8 @@ Multipart uploading allows files to be split into many chunks and uploaded in pa
6
7
 
7
8
  ## What's New
8
9
 
10
+ **0.0.10.6** - See pull request [23](https://github.com/maxgillett/s3_multipart/pull/23) for detailed changes. Changes will be documented in README soon.
11
+
9
12
  **0.0.10.5** - See pull request [16](https://github.com/maxgillett/s3_multipart/pull/16) and [18](https://github.com/maxgillett/s3_multipart/pull/18) for detailed changes.
10
13
 
11
14
  **0.0.10.4** - Fixed a race condition that led to incorrect upload progress feedback.
@@ -1,6 +1,6 @@
1
1
  module S3Multipart
2
2
  class UploadsController < ApplicationController
3
-
3
+
4
4
  def create
5
5
  begin
6
6
  upload = Upload.create(params)
@@ -20,9 +20,9 @@ module S3Multipart
20
20
  return complete_upload if params[:parts]
21
21
  return sign_batch if params[:content_lengths]
22
22
  return sign_part if params[:content_length]
23
- end
23
+ end
24
24
 
25
- private
25
+ private
26
26
 
27
27
  def sign_batch
28
28
  begin
@@ -7,12 +7,12 @@ module S3Multipart
7
7
 
8
8
  def self.create(params)
9
9
  response = initiate(params)
10
- super(key: response["key"], upload_id: response["upload_id"], name: response["name"], uploader: params["uploader"], size: params["content_size"])
10
+ super(key: response["key"], upload_id: response["upload_id"], name: response["name"], uploader: params["uploader"], size: params["content_size"], context: params["context"].to_s)
11
11
  end
12
12
 
13
13
  def execute_callback(stage, session)
14
14
  controller = deserialize(uploader)
15
-
15
+
16
16
  case stage
17
17
  when :begin
18
18
  controller.on_begin_callback.call(self, session) if controller.on_begin_callback
@@ -43,7 +43,7 @@ module S3Multipart
43
43
  types = deserialize(self.uploader).file_types
44
44
 
45
45
  unless types.blank? || types.include?(ext)
46
- raise FileTypeError, I18n.t("s3_multipart.errors.types", types: upload.deserialize(upload.uploader).file_types.join(", "))
46
+ raise FileTypeError, I18n.t("s3_multipart.errors.types", types: types.join(", "))
47
47
  end
48
48
  end
49
49
 
@@ -5,6 +5,7 @@ function S3MP(options) {
5
5
  , S3MP = this;
6
6
 
7
7
  _.extend(this, options);
8
+ this.headers = _.object(_.map(options.headers, function(v,k) { return ["x-amz-" + k.toLowerCase(), v] }));
8
9
 
9
10
  this.uploadList = [];
10
11
 
@@ -18,7 +19,7 @@ function S3MP(options) {
18
19
  var i = [];
19
20
  function beginUpload(pipes, uploadObj) {
20
21
  var key = uploadObj.key
21
- , num_parts = uploadObj.parts.length
22
+ , num_parts = uploadObj.parts.length;
22
23
 
23
24
  if (typeof i[key] === "undefined") {
24
25
  i[key] = 0;
@@ -47,6 +48,7 @@ function S3MP(options) {
47
48
  var parts, i, ETag;
48
49
 
49
50
  parts = uploadObj.parts;
51
+ finished_part.status = "complete";
50
52
 
51
53
  // Append the ETag (in the response header) to the ETags array
52
54
  ETag = finished_part.xhr.getResponseHeader("ETag");
@@ -141,12 +143,6 @@ function S3MP(options) {
141
143
  }
142
144
 
143
145
  _.each(files, function(file, key) {
144
- if (file.size < 5000000) {
145
- return S3MP.onError({name: "FileSizeError", message: "File size is too small"})
146
- // This should still work. The multipart API just can't be used b/c Amazon doesn't allow
147
- // multipart file uploads that are less than 5 mb in size.
148
- }
149
-
150
146
  var upload = new Upload(file, S3MP, key);
151
147
  S3MP.uploadList.push(upload);
152
148
  upload.init();
@@ -161,6 +157,8 @@ S3MP.prototype.initiateMultipart = function(upload, cb) {
161
157
  body = JSON.stringify({ object_name : upload.name,
162
158
  content_type : upload.type,
163
159
  content_size : upload.size,
160
+ headers : this.headers,
161
+ context : $(this.fileInputElement).data("context"),
164
162
  uploader : $(this.fileInputElement).data("uploader")
165
163
  });
166
164
 
@@ -176,7 +174,7 @@ S3MP.prototype.signPartRequests = function(id, object_name, upload_id, parts, cb
176
174
  return memo + "-" + part.size;
177
175
  }, parts[0].size);
178
176
 
179
- url = "s3_multipart/uploads/"+id;
177
+ url = "/s3_multipart/uploads/"+id;
180
178
  body = JSON.stringify({ object_name : object_name,
181
179
  upload_id : upload_id,
182
180
  content_lengths : content_lengths
@@ -189,7 +187,7 @@ S3MP.prototype.signPartRequests = function(id, object_name, upload_id, parts, cb
189
187
  S3MP.prototype.completeMultipart = function(uploadObj, cb) {
190
188
  var url, body, xhr;
191
189
 
192
- url = 's3_multipart/uploads/'+uploadObj.id;
190
+ url = '/s3_multipart/uploads/'+uploadObj.id;
193
191
  body = JSON.stringify({ object_name : uploadObj.object_name,
194
192
  upload_id : uploadObj.upload_id,
195
193
  content_length : uploadObj.size,
@@ -210,7 +208,7 @@ S3MP.prototype.deliverRequest = function(xhr, body, cb) {
210
208
  if (response.error) {
211
209
  return self.onError({
212
210
  name: "ServerResponse",
213
- message: "The server responded with an error"
211
+ message: response.error
214
212
  });
215
213
  }
216
214
  cb(response);
@@ -63,11 +63,8 @@ function Upload(file, o, key) {
63
63
 
64
64
  upload.signPartRequests(id, object_name, upload_id, parts, function(response) {
65
65
  _.each(parts, function(part, key) {
66
- var xhr = part.xhr;
67
-
68
- xhr.open('PUT', 'http://'+upload.bucket+'.s3.amazonaws.com/'+object_name+'?partNumber='+part.num+'&uploadId='+upload_id, true);
69
- xhr.setRequestHeader('x-amz-date', response[key].date);
70
- xhr.setRequestHeader('Authorization', response[key].authorization);
66
+ part.date = response[key].date;
67
+ part.auth = response[key].authorization;
71
68
 
72
69
  // Notify handler that an xhr request has been opened
73
70
  upload.handler.beginUpload(pipes, upload);
@@ -7,6 +7,7 @@ function UploadPart(blob, key, upload) {
7
7
  this.size = blob.size;
8
8
  this.blob = blob;
9
9
  this.num = key;
10
+ this.upload = upload;
10
11
 
11
12
  this.xhr = xhr = upload.createXhrRequest();
12
13
  xhr.onload = function() {
@@ -16,7 +17,7 @@ function UploadPart(blob, key, upload) {
16
17
  upload.handler.onError(upload, part);
17
18
  };
18
19
  xhr.upload.onprogress = _.throttle(function(e) {
19
- if (upload.inprogress[key] != 0) {
20
+ if (e.lengthComputable) {
20
21
  upload.inprogress[key] = e.loaded;
21
22
  }
22
23
  }, 1000);
@@ -24,6 +25,10 @@ function UploadPart(blob, key, upload) {
24
25
  };
25
26
 
26
27
  UploadPart.prototype.activate = function() {
28
+ this.xhr.open('PUT', 'http://'+this.upload.bucket+'.s3.amazonaws.com/'+this.upload.object_name+'?partNumber='+this.num+'&uploadId='+this.upload.upload_id, true);
29
+ this.xhr.setRequestHeader('x-amz-date', this.date);
30
+ this.xhr.setRequestHeader('Authorization', this.auth);
31
+
27
32
  this.xhr.send(this.blob);
28
33
  this.status = "active";
29
34
  };
@@ -8,6 +8,7 @@ module S3Multipart
8
8
 
9
9
  def create_latest_migrations
10
10
  copy_file "add_size_column_to_s3_multipart_uploads.rb", "db/migrate/#{migration_time}_add_size_to_s3_multipart_uploads.rb"
11
+ copy_file "add_context_column_to_s3_multipart_uploads.rb", "db/migrate/#{migration_time}_add_context_to_s3_multipart_uploads.rb"
11
12
  end
12
13
 
13
14
  private
@@ -0,0 +1,6 @@
1
+ class AddContextToS3MultipartUploads < ActiveRecord::Migration
2
+ def change
3
+ add_column :s3_multipart_uploads, :context, :text
4
+ end
5
+ end
6
+
@@ -2,4 +2,4 @@ development:
2
2
  access_key_id: ""
3
3
  secret_access_key: ""
4
4
  bucket: ""
5
- revision: "#.#.#"
5
+ revision: "#.#.#.#"
@@ -8,6 +8,8 @@ class CreateS3MultipartUploads < ActiveRecord::Migration
8
8
  t.string :name
9
9
  t.string :uploader
10
10
  t.integer :size
11
+ # additional options useful for constructing associations for the uploaded model
12
+ t.text :context
11
13
 
12
14
  t.timestamps
13
15
  end
@@ -31,7 +31,7 @@ module S3Multipart
31
31
  request[key.to_s.split("_").map(&:capitalize).join("-")] = val
32
32
  end
33
33
  request.body = body if body
34
-
34
+
35
35
  @response = http.request(request)
36
36
  end
37
37
 
@@ -31,7 +31,7 @@ module S3Multipart
31
31
  def sign_part(options)
32
32
  url = "/#{options[:object_name]}?partNumber=#{options[:part_number]}&uploadId=#{options[:upload_id]}"
33
33
  authorization, date = sign_request verb: 'PUT', url: URI.escape(url), content_length: options[:content_length]
34
-
34
+
35
35
  { authorization: authorization, date: date }
36
36
  end
37
37
 
@@ -39,7 +39,7 @@ module S3Multipart
39
39
  options[:content_type] = "application/xml"
40
40
 
41
41
  url = URI.escape("/#{options[:object_name]}?uploadId=#{options[:upload_id]}")
42
-
42
+
43
43
  body = format_part_list_in_xml(options)
44
44
  headers = { content_type: options[:content_type],
45
45
  content_length: options[:content_length] }
@@ -101,7 +101,7 @@ module S3Multipart
101
101
  request_parts << "/#{Config.instance.bucket_name}#{options[:url]}"
102
102
  unsigned_request = request_parts.join("\n")
103
103
  signature = Base64.strict_encode64(OpenSSL::HMAC.digest('sha1', Config.instance.s3_secret_key, unsigned_request))
104
-
104
+
105
105
  authorization = "AWS" + " " + Config.instance.s3_access_key + ":" + signature
106
106
  end
107
107
 
@@ -5,7 +5,7 @@ module S3Multipart
5
5
  attr_accessor :file_types, :size_limits
6
6
 
7
7
  def accept(types)
8
- self.file_types = types
8
+ self.file_types = types
9
9
  end
10
10
 
11
11
  def limit(sizes)
@@ -1,5 +1,5 @@
1
1
  module S3Multipart
2
- VERSION = "0.0.10.5"
2
+ VERSION = "0.0.10.6"
3
3
  BREAKING_CHANGES = {
4
4
  :"0.0.10.2" => 'Modifications made to the database table used by the gem are now handled by migrations. If you are upgrading versions, run `rails g s3_multipart:install_new_migrations` followed by `rake db:migrate`. Fresh installs do not require subsequent migrations. The current version must now also be passed in to the gem\'s configuration function to alert you of breaking changes. This is done by setting a revision yml variable. See the section regarding the aws.yml file in the readme section below (just before "Getting Started").'
5
5
  }
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "s3_multipart",
3
- "version": "0.0.10.3",
3
+ "version": "0.0.10.5",
4
4
  "devDependencies": {
5
- "grunt": "latest",
6
- "grunt-contrib-uglify": "latest",
5
+ "grunt": "0.3.17",
7
6
  "grunt-jasmine-runner": "latest"
8
7
  }
9
8
  }
@@ -24,7 +24,6 @@ Gem::Specification.new do |s|
24
24
  s.add_development_dependency 'combustion', '~> 0.3.3'
25
25
  s.add_development_dependency "rails"
26
26
  s.add_development_dependency "sqlite3"
27
- s.add_development_dependency 'rspec'
28
- s.add_development_dependency 'rspec-rails'
27
+ s.add_development_dependency 'rspec-rails', '~> 2.14', '>= 2.14.2'
29
28
  s.add_development_dependency 'capybara'
30
- end
29
+ end
@@ -9,6 +9,7 @@ describe "An upload object" do
9
9
  end
10
10
 
11
11
  it "should initiate an upload" do
12
+ @upload.stub(:unique_name) {'name'}
12
13
  response = @upload.initiate( object_name: "example_object.wmv",
13
14
  content_type: "video/x-ms-wmv" )
14
15
 
@@ -44,4 +45,4 @@ describe "An upload object" do
44
45
 
45
46
  response[:error].should eql("Upload does not exist")
46
47
  end
47
- end
48
+ end
@@ -172,6 +172,7 @@ S3MP.prototype.initiateMultipart = function(upload, cb) {
172
172
  content_type : upload.type,
173
173
  content_size : upload.size,
174
174
  headers : this.headers,
175
+ context : $(this.fileInputElement).data("context"),
175
176
  uploader : $(this.fileInputElement).data("uploader")
176
177
  });
177
178
 
@@ -405,6 +406,7 @@ function Upload(file, o, key) {
405
406
  _.each(parts, function(part, key) {
406
407
  part.date = response[key].date;
407
408
  part.auth = response[key].authorization;
409
+
408
410
  // Notify handler that an xhr request has been opened
409
411
  upload.handler.beginUpload(pipes, upload);
410
412
  });
@@ -461,4 +463,4 @@ return S3MP;
461
463
 
462
464
  }());
463
465
 
464
- }(this));
466
+ }(this));
@@ -1 +1 @@
1
- (function(e){e.S3MP=function(){function t(t){var r,i=[],s=this;_.extend(this,t),this.uploadList=[],this.handler={beginUpload:function(){function t(t,n){var r=n.key,i=n.parts.length;typeof e[r]=="undefined"&&(e[r]=0),e[r]++;if(e[r]===i){for(var o=0;o<t;o++)n.parts[o].activate();s.handler.startProgressTimer(r),s.onStart(n)}}var e=[];return t}(),onError:function(e,t){},onPartSuccess:function(e,t){var n,r,i;n=e.parts,i=t.xhr.getResponseHeader("ETag"),e.Etags.push({ETag:i.replace(/\"/g,""),partNum:t.num}),e.uploaded+=t.size,e.inprogress[t.num]=0,r=_.indexOf(n,t),n.splice(r,1),n.length&&(r=_.findIndex(n,function(e,t,n){if(e.status!=="active")return!0}),r!==-1&&n[r].activate()),n.length||this.onComplete(e)},onComplete:function(e){var t=_.indexOf(s.uploadList,e);this.clearProgressTimer(t),s.completeMultipart(e,function(t){t.location&&s.onComplete(e)})},onProgress:function(e,t,n,r,i){s.onProgress(e,t,n,r,i)},startProgressTimer:function(){var t=[],n=function(n){i[n]=e.setInterval(function(){var e,r,i,o,u;typeof t[n]=="undefined"&&(t[n]=0),e=s.uploadList[n],r=e.size,i=e.uploaded,_.each(e.inprogress,function(e){i+=e}),o=i/r*100,u=i-t[n],t[n]=i,e.handler.onProgress(n,r,i,o,u)},1e3)};return n}(),clearProgressTimer:function(t){e.clearInterval(i[t])}},this.fileSelector?r=$(this.fileSelector).get(0).files:r=this.fileList,_.each(r,function(e,t){if(e.size<5e6)return s.onError({name:"FileSizeError",message:"File size is too small"});var r=new n(e,s,t);s.uploadList.push(r),r.init()})}function n(e,t,n){function i(){var t,i,s,o,u,a,f,l,c;t=this,this.key=n,this.file=e,this.name=e.name,this.size=e.size,this.type=e.type,this.Etags=[],this.inprogress=[],this.uploaded=0,this.status="",this.size>1e9?(num_segs=100,l=10):this.size>5e8?(num_segs=50,l=5):this.size>1e8?(num_segs=20,l=5):this.size>5e7?(num_segs=5,l=2):this.size>1e7?(num_segs=2,l=2):(num_segs=1,l=1),a=_.range(num_segs+1),f=_.map(a,function(t){return Math.round(t*(e.size/num_segs))}),t.sliceBlob=="Unsupported"?this.parts=[new r(e,0,t)]:(this.parts=_.map(f,function(n,i){return c=t.sliceBlob(e,n,f[i+1]),new r(c,i+1,t)}),this.parts.pop()),this.init=function(){t.initiateMultipart(t,function(e){var n=t.id=e.id,r=t.upload_id=e.upload_id,i=t.object_name=e.key,s=t.parts;t.signPartRequests(n,i,r,s,function(e){_.each(s,function(n,s){var o=n.xhr;o.open("PUT","http://"+t.bucket+".s3.amazonaws.com/"+i+"?partNumber="+n.num+"&uploadId="+r,!0),o.setRequestHeader("x-amz-date",e[s].date),o.setRequestHeader("Authorization",e[s].authorization),t.handler.beginUpload(l,t)})})})}}return i.prototype=t,new i}function r(e,t,n){var r,i;r=this,this.size=e.size,this.blob=e,this.num=t,this.xhr=i=n.createXhrRequest(),i.onload=function(){n.handler.onPartSuccess(n,r)},i.onerror=function(){n.handler.onError(n,r)},i.upload.onprogress=_.throttle(function(e){n.inprogress[t]!=0&&(n.inprogress[t]=e.loaded)},1e3)}return _.mixin({findIndex:function(e,t){for(var n=0;n<e.length;n++)if(t(e[n],n,e))return n;return-1}}),t.prototype.initiateMultipart=function(e,t){var n,r,i;n="/s3_multipart/uploads",r=JSON.stringify({object_name:e.name,content_type:e.type,content_size:e.size,uploader:$(this.fileInputElement).data("uploader")}),i=this.createXhrRequest("POST",n),this.deliverRequest(i,r,t)},t.prototype.signPartRequests=function(e,t,n,r,i){var s,o,u,a;s=_.reduce(_.rest(r),function(e,t){return e+"-"+t.size},r[0].size),o="s3_multipart/uploads/"+e,u=JSON.stringify({object_name:t,upload_id:n,content_lengths:s}),a=this.createXhrRequest("PUT",o),this.deliverRequest(a,u,i)},t.prototype.completeMultipart=function(e,t){var n,r,i;n="s3_multipart/uploads/"+e.id,r=JSON.stringify({object_name:e.object_name,upload_id:e.upload_id,content_length:e.size,parts:e.Etags}),i=this.createXhrRequest("PUT",n),this.deliverRequest(i,r,t)},t.prototype.deliverRequest=function(e,t,n){var r=this;e.onload=function(){response=JSON.parse(this.responseText);if(response.error)return r.onError({name:"ServerResponse",message:"The server responded with an error"});n(response)},e.onerror=function(){},e.setRequestHeader("Content-Type","application/json"),e.setRequestHeader("X-CSRF-Token",$('meta[name="csrf-token"]').attr("content")),e.send(t)},t.prototype.createXhrRequest=function(){var e;return typeof XMLHttpRequest.constructor=="function"?e=XMLHttpRequest:typeof XDomainRequest!="undefined"?e=XDomainRequest:e=null,function(t,n,r,i){var s,o,i=!0;return s=Array.prototype.slice.call(arguments),typeof s[0]=="undefined"&&(r=null,i=!1),o=new e,i&&o.open(t,n,!0),o.onreadystatechange=r,o}}(),t.prototype.sliceBlob=function(){try{var e=new Blob}catch(t){return"Unsupported"}return e.slice?function(e,t,n){return e.slice(t,n)}:e.mozSlice?function(e,t,n){return e.mozSlice(t,n)}:e.webkitSlice?function(e,t,n){return e.webkitSlice(t,n)}:"Unsupported"}(),t.prototype._returnUploadObj=function(e){var t=_.find(this.uploadList,function(t){return t.key===e});return t},t.prototype.cancel=function(e){var t,n;t=this._returnUploadObj(e),n=_.indexOf(this.uploadList,t),this.uploadList.splice(n,n+1),this.onCancel()},t.prototype.pause=function(e){var t=this._returnUploadObj(e);_.each(t.parts,function(e,t,n){e.status=="active"&&e.pause()}),this.onPause()},t.prototype.resume=function(e){var t=this._returnUploadObj(e);_.each(t.parts,function(e,t,n){e.status=="paused"&&e.activate()}),this.onResume()},r.prototype.activate=function(){this.xhr.send(this.blob),this.status="active"},r.prototype.pause=function(){this.xhr.abort(),this.status="paused"},t}()})(this);
1
+ (function(e){e.S3MP=function(){function t(t){var r,i=[],s=this;_.extend(this,t),this.headers=_.object(_.map(t.headers,function(e,t){return["x-amz-"+t.toLowerCase(),e]})),this.uploadList=[],this.handler={beginUpload:function(){function t(t,n){var r=n.key,i=n.parts.length;typeof e[r]=="undefined"&&(e[r]=0),e[r]++;if(e[r]===i){for(var o=0;o<t;o++)n.parts[o].activate();s.handler.startProgressTimer(r),s.onStart(n)}}var e=[];return t}(),onError:function(e,t){},onPartSuccess:function(e,t){var n,r,i;n=e.parts,t.status="complete",i=t.xhr.getResponseHeader("ETag"),e.Etags.push({ETag:i.replace(/\"/g,""),partNum:t.num}),e.uploaded+=t.size,e.inprogress[t.num]=0,r=_.indexOf(n,t),n.splice(r,1),n.length&&(r=_.findIndex(n,function(e,t,n){if(e.status!=="active")return!0}),r!==-1&&n[r].activate()),n.length||this.onComplete(e)},onComplete:function(e){var t=_.indexOf(s.uploadList,e);this.clearProgressTimer(t),s.completeMultipart(e,function(t){t.location&&s.onComplete(e)})},onProgress:function(e,t,n,r,i){s.onProgress(e,t,n,r,i)},startProgressTimer:function(){var t=[],n=function(n){i[n]=e.setInterval(function(){var e,r,i,o,u;typeof t[n]=="undefined"&&(t[n]=0),e=s.uploadList[n],r=e.size,i=e.uploaded,_.each(e.inprogress,function(e){i+=e}),o=i/r*100,u=i-t[n],t[n]=i,e.handler.onProgress(n,r,i,o,u)},1e3)};return n}(),clearProgressTimer:function(t){e.clearInterval(i[t])}},this.fileSelector?r=$(this.fileSelector).get(0).files:r=this.fileList,_.each(r,function(e,t){var r=new n(e,s,t);s.uploadList.push(r),r.init()})}function n(e,t,n){function i(){var t,i,s,o,u,a,f,l,c;t=this,this.key=n,this.file=e,this.name=e.name,this.size=e.size,this.type=e.type,this.Etags=[],this.inprogress=[],this.uploaded=0,this.status="",this.size>1e9?(num_segs=100,l=10):this.size>5e8?(num_segs=50,l=5):this.size>1e8?(num_segs=20,l=5):this.size>5e7?(num_segs=5,l=2):this.size>1e7?(num_segs=2,l=2):(num_segs=1,l=1),a=_.range(num_segs+1),f=_.map(a,function(t){return Math.round(t*(e.size/num_segs))}),t.sliceBlob=="Unsupported"?this.parts=[new r(e,0,t)]:(this.parts=_.map(f,function(n,i){return c=t.sliceBlob(e,n,f[i+1]),new r(c,i+1,t)}),this.parts.pop()),this.init=function(){t.initiateMultipart(t,function(e){var n=t.id=e.id,r=t.upload_id=e.upload_id,i=t.object_name=e.key,s=t.parts;t.signPartRequests(n,i,r,s,function(e){_.each(s,function(n,r){n.date=e[r].date,n.auth=e[r].authorization,t.handler.beginUpload(l,t)})})})}}return i.prototype=t,new i}function r(e,t,n){var r,i;r=this,this.size=e.size,this.blob=e,this.num=t,this.upload=n,this.xhr=i=n.createXhrRequest(),i.onload=function(){n.handler.onPartSuccess(n,r)},i.onerror=function(){n.handler.onError(n,r)},i.upload.onprogress=_.throttle(function(e){e.lengthComputable&&(n.inprogress[t]=e.loaded)},1e3)}return _.mixin({findIndex:function(e,t){for(var n=0;n<e.length;n++)if(t(e[n],n,e))return n;return-1}}),t.prototype.initiateMultipart=function(e,t){var n,r,i;n="/s3_multipart/uploads",r=JSON.stringify({object_name:e.name,content_type:e.type,content_size:e.size,headers:this.headers,context:$(this.fileInputElement).data("context"),uploader:$(this.fileInputElement).data("uploader")}),i=this.createXhrRequest("POST",n),this.deliverRequest(i,r,t)},t.prototype.signPartRequests=function(e,t,n,r,i){var s,o,u,a;s=_.reduce(_.rest(r),function(e,t){return e+"-"+t.size},r[0].size),o="/s3_multipart/uploads/"+e,u=JSON.stringify({object_name:t,upload_id:n,content_lengths:s}),a=this.createXhrRequest("PUT",o),this.deliverRequest(a,u,i)},t.prototype.completeMultipart=function(e,t){var n,r,i;n="/s3_multipart/uploads/"+e.id,r=JSON.stringify({object_name:e.object_name,upload_id:e.upload_id,content_length:e.size,parts:e.Etags}),i=this.createXhrRequest("PUT",n),this.deliverRequest(i,r,t)},t.prototype.deliverRequest=function(e,t,n){var r=this;e.onload=function(){response=JSON.parse(this.responseText);if(response.error)return r.onError({name:"ServerResponse",message:response.error});n(response)},e.onerror=function(){},e.setRequestHeader("Content-Type","application/json"),e.setRequestHeader("X-CSRF-Token",$('meta[name="csrf-token"]').attr("content")),e.send(t)},t.prototype.createXhrRequest=function(){var e;return typeof XMLHttpRequest.constructor=="function"?e=XMLHttpRequest:typeof XDomainRequest!="undefined"?e=XDomainRequest:e=null,function(t,n,r,i){var s,o,i=!0;return s=Array.prototype.slice.call(arguments),typeof s[0]=="undefined"&&(r=null,i=!1),o=new e,i&&o.open(t,n,!0),o.onreadystatechange=r,o}}(),t.prototype.sliceBlob=function(){try{var e=new Blob}catch(t){return"Unsupported"}return e.slice?function(e,t,n){return e.slice(t,n)}:e.mozSlice?function(e,t,n){return e.mozSlice(t,n)}:e.webkitSlice?function(e,t,n){return e.webkitSlice(t,n)}:"Unsupported"}(),t.prototype._returnUploadObj=function(e){var t=_.find(this.uploadList,function(t){return t.key===e});return t},t.prototype.cancel=function(e){var t,n;t=this._returnUploadObj(e),n=_.indexOf(this.uploadList,t),this.uploadList.splice(n,n+1),this.onCancel()},t.prototype.pause=function(e){var t=this._returnUploadObj(e);_.each(t.parts,function(e,t,n){e.status=="active"&&e.pause()}),this.onPause()},t.prototype.resume=function(e){var t=this._returnUploadObj(e);_.each(t.parts,function(e,t,n){e.status=="paused"&&e.activate()}),this.onResume()},r.prototype.activate=function(){this.xhr.open("PUT","http://"+this.upload.bucket+".s3.amazonaws.com/"+this.upload.object_name+"?partNumber="+this.num+"&uploadId="+this.upload.upload_id,!0),this.xhr.setRequestHeader("x-amz-date",this.date),this.xhr.setRequestHeader("Authorization",this.auth),this.xhr.send(this.blob),this.status="active"},r.prototype.pause=function(){this.xhr.abort(),this.status="paused"},t}()})(this);
metadata CHANGED
@@ -1,125 +1,117 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3_multipart
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10.5
4
+ version: 0.0.10.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Gillett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-19 00:00:00.000000000 Z
11
+ date: 2014-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uuid
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.3.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.3.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: xml-simple
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.1.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.1.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: combustion
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.3.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.3.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rails
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rspec
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - '>='
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - '>='
80
+ - - ">="
95
81
  - !ruby/object:Gem::Version
96
82
  version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rspec-rails
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
- - - '>='
87
+ - - "~>"
102
88
  - !ruby/object:Gem::Version
103
- version: '0'
89
+ version: '2.14'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 2.14.2
104
93
  type: :development
105
94
  prerelease: false
106
95
  version_requirements: !ruby/object:Gem::Requirement
107
96
  requirements:
108
- - - '>='
97
+ - - "~>"
109
98
  - !ruby/object:Gem::Version
110
- version: '0'
99
+ version: '2.14'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 2.14.2
111
103
  - !ruby/object:Gem::Dependency
112
104
  name: capybara
113
105
  requirement: !ruby/object:Gem::Requirement
114
106
  requirements:
115
- - - '>='
107
+ - - ">="
116
108
  - !ruby/object:Gem::Version
117
109
  version: '0'
118
110
  type: :development
119
111
  prerelease: false
120
112
  version_requirements: !ruby/object:Gem::Requirement
121
113
  requirements:
122
- - - '>='
114
+ - - ">="
123
115
  - !ruby/object:Gem::Version
124
116
  version: '0'
125
117
  description: 'See github for installation and configuration '
@@ -130,7 +122,7 @@ extensions: []
130
122
  extra_rdoc_files:
131
123
  - README.md
132
124
  files:
133
- - .gitignore
125
+ - ".gitignore"
134
126
  - Gemfile
135
127
  - Gemfile.lock
136
128
  - LICENSE.txt
@@ -150,6 +142,7 @@ files:
150
142
  - javascripts/uploadpart.js
151
143
  - lib/generators/s3_multipart/install_generator.rb
152
144
  - lib/generators/s3_multipart/install_new_migrations_generator.rb
145
+ - lib/generators/s3_multipart/templates/add_context_to_s3_multipart_uploads.rb
153
146
  - lib/generators/s3_multipart/templates/add_size_column_to_s3_multipart_uploads.rb
154
147
  - lib/generators/s3_multipart/templates/add_uploader_column_to_model.rb
155
148
  - lib/generators/s3_multipart/templates/aws.yml
@@ -272,17 +265,17 @@ require_paths:
272
265
  - lib
273
266
  required_ruby_version: !ruby/object:Gem::Requirement
274
267
  requirements:
275
- - - '>='
268
+ - - ">="
276
269
  - !ruby/object:Gem::Version
277
270
  version: '0'
278
271
  required_rubygems_version: !ruby/object:Gem::Requirement
279
272
  requirements:
280
- - - '>='
273
+ - - ">="
281
274
  - !ruby/object:Gem::Version
282
275
  version: '0'
283
276
  requirements: []
284
277
  rubyforge_project:
285
- rubygems_version: 2.0.3
278
+ rubygems_version: 2.2.2
286
279
  signing_key:
287
280
  specification_version: 4
288
281
  summary: Upload directly to S3 using multipart uploading