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 +4 -4
- data/.gitignore +4 -0
- data/Gemfile +1 -11
- data/Gemfile.lock +17 -21
- data/README.md +3 -0
- data/app/controllers/s3_multipart/uploads_controller.rb +3 -3
- data/app/models/s3_multipart/upload.rb +3 -3
- data/javascripts/s3mp.js +8 -10
- data/javascripts/upload.js +2 -5
- data/javascripts/uploadpart.js +6 -1
- data/lib/generators/s3_multipart/install_new_migrations_generator.rb +1 -0
- data/lib/generators/s3_multipart/templates/add_context_to_s3_multipart_uploads.rb +6 -0
- data/lib/generators/s3_multipart/templates/aws.yml +1 -1
- data/lib/generators/s3_multipart/templates/uploads_table_migration.rb +2 -0
- data/lib/s3_multipart/http/net_http.rb +1 -1
- data/lib/s3_multipart/transfer_helpers.rb +3 -3
- data/lib/s3_multipart/uploader/validations.rb +1 -1
- data/lib/s3_multipart/version.rb +1 -1
- data/package.json +2 -3
- data/s3_multipart.gemspec +2 -3
- data/spec/unit/upload_spec.rb +2 -1
- data/vendor/assets/javascripts/s3_multipart/lib.js +3 -1
- data/vendor/assets/javascripts/s3_multipart/lib.min.js +1 -1
- metadata +29 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e74a7aee76d8f60af7b749993e1257c1392f3324
|
4
|
+
data.tar.gz: b89221f39db1562e39906af3ede3c3b589789489
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccd1414d670078a844ee5a3aa18499c318fec1a54e6e5b834d0b2dd7e55ac966ac7df4a5108e6dc879e937755d55642ca939c76e6fd7608919eadd6150939228
|
7
|
+
data.tar.gz: 86f8560e32863f0534adf0fd5681321ba48885affe480f98fa031491d272770591d3c83694a29abc7ab0c2e98adf750837e430777d331a2413398d3cb97d0de9
|
data/.gitignore
CHANGED
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
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
s3_multipart (0.0.10.
|
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.
|
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.
|
87
|
-
systemu (~> 2.
|
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.
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
rspec-
|
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.
|
134
|
-
rspec-expectations (~> 2.
|
135
|
-
rspec-mocks (~> 2.
|
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.
|
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.
|
157
|
+
uuid (2.3.7)
|
161
158
|
macaddr (~> 1.0)
|
162
159
|
websocket (1.0.6)
|
163
|
-
xml-simple (1.1.
|
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:
|
46
|
+
raise FileTypeError, I18n.t("s3_multipart.errors.types", types: types.join(", "))
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
data/javascripts/s3mp.js
CHANGED
@@ -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:
|
211
|
+
message: response.error
|
214
212
|
});
|
215
213
|
}
|
216
214
|
cb(response);
|
data/javascripts/upload.js
CHANGED
@@ -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
|
-
|
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);
|
data/javascripts/uploadpart.js
CHANGED
@@ -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 (
|
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
|
@@ -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
|
|
data/lib/s3_multipart/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module S3Multipart
|
2
|
-
VERSION = "0.0.10.
|
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
|
}
|
data/package.json
CHANGED
data/s3_multipart.gemspec
CHANGED
@@ -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
|
data/spec/unit/upload_spec.rb
CHANGED
@@ -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){
|
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.
|
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-
|
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: '
|
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: '
|
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.
|
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
|