s3_multipart 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +8 -1
- data/README.md +150 -42
- data/Rakefile +10 -0
- data/app/controllers/s3_multipart/application_controller.rb +6 -3
- data/app/controllers/s3_multipart/uploads_controller.rb +30 -29
- data/app/models/s3_multipart/upload.rb +13 -5
- data/grunt.js +44 -0
- data/javascripts/footer.js +5 -0
- data/javascripts/header.js +14 -0
- data/javascripts/libs/underscore.js +1 -0
- data/javascripts/s3mp.js +329 -0
- data/javascripts/upload.js +76 -0
- data/javascripts/uploadpart.js +32 -0
- data/lib/generators/s3_multipart/install_generator.rb +30 -0
- data/lib/generators/s3_multipart/templates/add_uploader_column_to_model.rb +7 -0
- data/lib/generators/s3_multipart/templates/aws.yml +4 -0
- data/lib/generators/s3_multipart/templates/configuration_initializer.rb +8 -0
- data/lib/generators/s3_multipart/templates/uploader.rb +29 -0
- data/{db/migrate/20110727184726_create_s3_multipart_uploads.rb → lib/generators/s3_multipart/templates/uploads_table_migration.rb} +2 -0
- data/lib/generators/s3_multipart/uploader_generator.rb +33 -0
- data/lib/s3_multipart/action_view_helpers/form_helper.rb +2 -1
- data/lib/s3_multipart/config.rb +12 -0
- data/lib/s3_multipart/http/net_http.rb +6 -6
- data/lib/s3_multipart/railtie.rb +12 -0
- data/lib/s3_multipart/transfer_helpers.rb +92 -0
- data/lib/s3_multipart/uploader/callbacks.rb +17 -0
- data/lib/s3_multipart/uploader/validations.rb +9 -0
- data/lib/s3_multipart/uploader.rb +27 -68
- data/lib/s3_multipart/version.rb +1 -1
- data/lib/s3_multipart.rb +4 -42
- data/package.json +9 -0
- data/s3_multipart.gemspec +6 -3
- data/spec/integration/uploads_controller_spec.rb +2 -1
- data/spec/internal/app/assets/javascripts/application.js +148 -63
- data/spec/internal/app/assets/stylesheets/application.css.scss +384 -0
- data/spec/internal/app/assets/stylesheets/font-awesome.scss +499 -0
- data/spec/internal/app/controllers/application_controller.rb +4 -1
- data/spec/internal/app/controllers/pages_controller.rb +3 -7
- data/spec/internal/app/models/user.rb +4 -0
- data/spec/internal/app/models/video.rb +5 -0
- data/spec/internal/app/uploaders/multipart/video_uploader.rb +32 -0
- data/spec/internal/app/views/pages/upload.html.erb +38 -4
- data/spec/internal/config/routes.rb +1 -1
- data/spec/internal/db/schema.rb +22 -14
- data/spec/internal/public/fonts/FontAwesome.otf +0 -0
- data/spec/internal/public/fonts/fontawesome-webfont.eot +0 -0
- data/spec/internal/public/fonts/fontawesome-webfont.ttf +0 -0
- data/spec/internal/public/fonts/fontawesome-webfont.woff +0 -0
- data/spec/internal/tmp/cache/sass/077f66d4d9153cfd737b81ab3f4c5d5858b0db3b/_grid-background.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_appearance.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_background-clip.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_background-origin.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_background-size.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_border-radius.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_box-shadow.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_box-sizing.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_box.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_columns.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_filter.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_font-face.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_hyphenation.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_images.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_inline-block.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_opacity.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_regions.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_shared.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_text-shadow.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_transform.scssc +0 -0
- data/spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_transition.scssc +0 -0
- data/spec/internal/tmp/cache/sass/351072894b53bf1a2d2af4bd57c177c805cf063e/_contrast.scssc +0 -0
- data/spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_css3.scssc +0 -0
- data/spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_support.scssc +0 -0
- data/spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_typography.scssc +0 -0
- data/spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_utilities.scssc +0 -0
- data/spec/internal/tmp/cache/sass/633bc5f017268b81a60f921876c980c4adcebb74/_base.scssc +0 -0
- data/spec/internal/tmp/cache/sass/633bc5f017268b81a60f921876c980c4adcebb74/_sprite-img.scssc +0 -0
- data/spec/internal/tmp/cache/sass/68dbce8ac3037e0cd797c9b5c6aa131096361144/_utilities.scssc +0 -0
- data/spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_clearfix.scssc +0 -0
- data/spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_float.scssc +0 -0
- data/spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_hacks.scssc +0 -0
- data/spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_min.scssc +0 -0
- data/spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_reset.scssc +0 -0
- data/spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_tag-cloud.scssc +0 -0
- data/spec/internal/tmp/cache/sass/775792c99f07f64e98296a8dc8c9d2c74a28fd8a/_reset.scssc +0 -0
- data/spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_ellipsis.scssc +0 -0
- data/spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_force-wrap.scssc +0 -0
- data/spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_nowrap.scssc +0 -0
- data/spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_replacement.scssc +0 -0
- data/spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_bullets.scssc +0 -0
- data/spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_horizontal-list.scssc +0 -0
- data/spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_inline-block-list.scssc +0 -0
- data/spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_inline-list.scssc +0 -0
- data/spec/internal/tmp/cache/sass/b1bb3e2fbcb5c6a71ea2273c6dcb7c8967d2a058/_alternating-rows-and-columns.scssc +0 -0
- data/spec/internal/tmp/cache/sass/b1bb3e2fbcb5c6a71ea2273c6dcb7c8967d2a058/_borders.scssc +0 -0
- data/spec/internal/tmp/cache/sass/b1bb3e2fbcb5c6a71ea2273c6dcb7c8967d2a058/_scaffolding.scssc +0 -0
- data/spec/internal/tmp/cache/sass/bc7f11d6e8f07a22f545deb35760cfc7830f3369/application.css.scssc +0 -0
- data/spec/internal/tmp/cache/sass/bc7f11d6e8f07a22f545deb35760cfc7830f3369/font-awesome.scssc +0 -0
- data/spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_color.scssc +0 -0
- data/spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_general.scssc +0 -0
- data/spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_sprites.scssc +0 -0
- data/spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_tables.scssc +0 -0
- data/spec/internal/tmp/cache/sass/d1da036a47062a9f69ce0327962c00aa77d2ea44/_hover-link.scssc +0 -0
- data/spec/internal/tmp/cache/sass/d1da036a47062a9f69ce0327962c00aa77d2ea44/_link-colors.scssc +0 -0
- data/spec/internal/tmp/cache/sass/d1da036a47062a9f69ce0327962c00aa77d2ea44/_unstyled-link.scssc +0 -0
- data/spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_links.scssc +0 -0
- data/spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_lists.scssc +0 -0
- data/spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_text.scssc +0 -0
- data/spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_vertical_rhythm.scssc +0 -0
- data/spec/internal/tmp/cache/sass/e2e5b9bb57a9d1b018b9f546bc8b16f6b2a627a9/_compass.scssc +0 -0
- data/spec/internal/tmp/cache/sass/e654955d4502954a409bf21071c0d98eb4ac2e9f/_utilities.scssc +0 -0
- data/spec/javascripts/UploadSpec.js +75 -0
- data/spec/javascripts/helpers/SpecHelper.js +9 -0
- data/spec/javascripts/support/jasmine.yml +84 -0
- data/spec/unit/upload_controller_spec.rb +31 -0
- data/spec/{requests/uploader_spec.rb → unit/upload_spec.rb} +9 -10
- data/spec/unit/uploader_module_spec.rb +31 -0
- data/vendor/assets/javascripts/s3_multipart/lib.js +456 -0
- data/vendor/assets/javascripts/s3_multipart/lib.min.js +1 -0
- metadata +103 -12
- data/.rspec +0 -1
- data/lib/s3_multipart/uploader/config.rb +0 -15
- data/spec/internal/app/assets/stylesheets/application.css +0 -0
- data/spec/internal/db/combustion_test.sqlite3 +0 -0
- data/vendor/assets/javascripts/s3_multipart/index.js +0 -1
- data/vendor/assets/javascripts/s3_multipart/s3_multipart.js +0 -478
@@ -0,0 +1,456 @@
|
|
1
|
+
(function(global) {
|
2
|
+
global.S3MP = (function() {
|
3
|
+
|
4
|
+
// Wrap this into underscore library extension
|
5
|
+
_.mixin({
|
6
|
+
findIndex : function (collection, filter) {
|
7
|
+
for (var i = 0; i < collection.length; i++) {
|
8
|
+
if (filter(collection[i], i, collection)) {
|
9
|
+
return i;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
return -1;
|
13
|
+
}
|
14
|
+
});
|
15
|
+
// S3MP Constructor
|
16
|
+
function S3MP(options) {
|
17
|
+
var files
|
18
|
+
, progress_timer = []
|
19
|
+
, S3MP = this;
|
20
|
+
|
21
|
+
_.extend(this, options);
|
22
|
+
|
23
|
+
this.uploadList = [];
|
24
|
+
|
25
|
+
// Handles all of the success/failure events, and
|
26
|
+
// progress notifiers
|
27
|
+
this.handler = {
|
28
|
+
|
29
|
+
// Activate an appropriate number of parts (number = pipes)
|
30
|
+
// when all of the parts have been successfully initialized
|
31
|
+
beginUpload: function() {
|
32
|
+
var i = [];
|
33
|
+
function beginUpload(pipes, uploadObj) {
|
34
|
+
var key = uploadObj.key
|
35
|
+
, num_parts = uploadObj.parts.length
|
36
|
+
|
37
|
+
if (typeof i[key] === "undefined") {
|
38
|
+
i[key] = 0;
|
39
|
+
}
|
40
|
+
|
41
|
+
i[key]++;
|
42
|
+
|
43
|
+
if (i[key] === num_parts) {
|
44
|
+
for (var j=0; j<pipes; j++) {
|
45
|
+
uploadObj.parts[j].activate();
|
46
|
+
}
|
47
|
+
S3MP.handler.startProgressTimer(key);
|
48
|
+
S3MP.onStart(uploadObj); // This probably needs to go somewhere else.
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return beginUpload;
|
52
|
+
}(),
|
53
|
+
|
54
|
+
// called when an upload is paused or the network connection cuts out
|
55
|
+
onError: function(uploadObj, part) {
|
56
|
+
// To-do
|
57
|
+
},
|
58
|
+
|
59
|
+
// called when a single part has successfully uploaded
|
60
|
+
onPartSuccess: function(uploadObj, finished_part) {
|
61
|
+
var parts, i, ETag;
|
62
|
+
|
63
|
+
parts = uploadObj.parts;
|
64
|
+
|
65
|
+
// Append the ETag (in the response header) to the ETags array
|
66
|
+
ETag = finished_part.xhr.getResponseHeader("ETag");
|
67
|
+
uploadObj.Etags.push({ ETag: ETag.replace(/\"/g, ''), partNum: finished_part.num });
|
68
|
+
|
69
|
+
// Increase the uploaded count and delete the finished part
|
70
|
+
uploadObj.uploaded += finished_part.size;
|
71
|
+
uploadObj.inprogress[finished_part.num] = 0;
|
72
|
+
i = _.indexOf(parts, finished_part);
|
73
|
+
parts.splice(i,1);
|
74
|
+
|
75
|
+
// activate one of the remaining parts
|
76
|
+
if (parts.length) {
|
77
|
+
i = _.findIndex(parts, function(el, index, collection) {
|
78
|
+
if (el.status !== "active") {
|
79
|
+
return true;
|
80
|
+
}
|
81
|
+
});
|
82
|
+
if (i !== -1){
|
83
|
+
parts[i].activate();
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
// If no parts remain then the upload has finished
|
88
|
+
if (!parts.length) {
|
89
|
+
this.onComplete(uploadObj);
|
90
|
+
}
|
91
|
+
},
|
92
|
+
|
93
|
+
// called when all parts have successfully uploaded
|
94
|
+
onComplete: function(uploadObj) {
|
95
|
+
var key = _.indexOf(S3MP.uploadList, uploadObj);
|
96
|
+
|
97
|
+
// Stop the onprogress timer
|
98
|
+
this.clearProgressTimer(key);
|
99
|
+
|
100
|
+
// Tell the server to put together the pieces
|
101
|
+
S3MP.completeMultipart(uploadObj, function(obj) {
|
102
|
+
// Notify the client that the upload has succeeded when we
|
103
|
+
// get confirmation from the server
|
104
|
+
if (obj.location) {
|
105
|
+
S3MP.onComplete(uploadObj);
|
106
|
+
}
|
107
|
+
});
|
108
|
+
|
109
|
+
},
|
110
|
+
|
111
|
+
// Called by progress_timer
|
112
|
+
onProgress: function(key, size, done, percent, speed) {
|
113
|
+
S3MP.onProgress(key, size, done, percent, speed);
|
114
|
+
},
|
115
|
+
|
116
|
+
startProgressTimer: function() {
|
117
|
+
var last_upload_chunk = [];
|
118
|
+
var fn = function(key) {
|
119
|
+
progress_timer[key] = global.setInterval(function() {
|
120
|
+
var upload, size, done, percent, speed;
|
121
|
+
|
122
|
+
if (typeof last_upload_chunk[key] === "undefined") {
|
123
|
+
last_upload_chunk[key] = 0;
|
124
|
+
}
|
125
|
+
|
126
|
+
upload = S3MP.uploadList[key];
|
127
|
+
size = upload.size;
|
128
|
+
done = upload.uploaded;
|
129
|
+
|
130
|
+
_.each(upload.inprogress,function(val) {
|
131
|
+
done += val;
|
132
|
+
});
|
133
|
+
|
134
|
+
percent = done/size * 100;
|
135
|
+
speed = done - last_upload_chunk[key];
|
136
|
+
last_upload_chunk[key] = done;
|
137
|
+
|
138
|
+
upload.handler.onProgress(key, size, done, percent, speed);
|
139
|
+
}, 1000);
|
140
|
+
};
|
141
|
+
return fn;
|
142
|
+
}(),
|
143
|
+
|
144
|
+
clearProgressTimer: function(key) {
|
145
|
+
global.clearInterval(progress_timer[key]);
|
146
|
+
}
|
147
|
+
|
148
|
+
};
|
149
|
+
|
150
|
+
// List of files may come from a FileList object or an array of files
|
151
|
+
if (this.fileSelector) {
|
152
|
+
files = $(this.fileSelector).get(0).files; // FileList object
|
153
|
+
} else {
|
154
|
+
files = this.fileList; // array specified in configuration
|
155
|
+
}
|
156
|
+
|
157
|
+
_.each(files, function(file, key) {
|
158
|
+
//Do validation for each file before creating a new upload object
|
159
|
+
// if (!file.type.match(/video/)) {
|
160
|
+
// return false;
|
161
|
+
// }
|
162
|
+
if (file.size < 5000000) {
|
163
|
+
return S3MP.onError({name: "FileSizeError", message: "File size is too small"})
|
164
|
+
}
|
165
|
+
|
166
|
+
var upload = new Upload(file, S3MP, key);
|
167
|
+
S3MP.uploadList.push(upload);
|
168
|
+
upload.init();
|
169
|
+
});
|
170
|
+
|
171
|
+
};
|
172
|
+
|
173
|
+
S3MP.prototype.initiateMultipart = function(upload, cb) {
|
174
|
+
var url, body, xhr;
|
175
|
+
|
176
|
+
url = '/s3_multipart/uploads';
|
177
|
+
body = JSON.stringify({ object_name : upload.name,
|
178
|
+
content_type : upload.type,
|
179
|
+
uploader : $(this.fileInputElement).data("uploader")
|
180
|
+
});
|
181
|
+
|
182
|
+
xhr = this.createXhrRequest('POST', url);
|
183
|
+
this.deliverRequest(xhr, body, cb);
|
184
|
+
|
185
|
+
};
|
186
|
+
|
187
|
+
S3MP.prototype.signPartRequests = function(id, object_name, upload_id, parts, cb) {
|
188
|
+
var content_lengths, url, body, xhr;
|
189
|
+
|
190
|
+
content_lengths = _.reduce(_.rest(parts), function(memo, part) {
|
191
|
+
return memo + "-" + part.size;
|
192
|
+
}, parts[0].size);
|
193
|
+
|
194
|
+
url = "s3_multipart/uploads/"+id;
|
195
|
+
body = JSON.stringify({ object_name : object_name,
|
196
|
+
upload_id : upload_id,
|
197
|
+
content_lengths : content_lengths
|
198
|
+
});
|
199
|
+
|
200
|
+
xhr = this.createXhrRequest('PUT', url);
|
201
|
+
this.deliverRequest(xhr, body, cb);
|
202
|
+
};
|
203
|
+
|
204
|
+
S3MP.prototype.completeMultipart = function(uploadObj, cb) {
|
205
|
+
var url, body, xhr;
|
206
|
+
|
207
|
+
url = 's3_multipart/uploads/'+uploadObj.id;
|
208
|
+
body = JSON.stringify({ object_name : uploadObj.object_name,
|
209
|
+
upload_id : uploadObj.upload_id,
|
210
|
+
content_length : uploadObj.size,
|
211
|
+
parts : uploadObj.Etags
|
212
|
+
});
|
213
|
+
|
214
|
+
xhr = this.createXhrRequest('PUT', url);
|
215
|
+
this.deliverRequest(xhr, body, cb);
|
216
|
+
};
|
217
|
+
|
218
|
+
// Specify callbacks, request body, and settings for requests that contact
|
219
|
+
// the site server, and send the request.
|
220
|
+
S3MP.prototype.deliverRequest = function(xhr, body, cb) {
|
221
|
+
var self = this;
|
222
|
+
|
223
|
+
xhr.onload = function() {
|
224
|
+
response = JSON.parse(this.responseText);
|
225
|
+
if (response.error) {
|
226
|
+
return self.onError({
|
227
|
+
name: "ServerResponse",
|
228
|
+
message: "The server responded with an error"
|
229
|
+
});
|
230
|
+
}
|
231
|
+
cb(response);
|
232
|
+
};
|
233
|
+
|
234
|
+
xhr.onerror = function() {
|
235
|
+
// To-do: Handle communication errors
|
236
|
+
};
|
237
|
+
|
238
|
+
xhr.setRequestHeader('Content-Type', 'application/json');
|
239
|
+
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
|
240
|
+
|
241
|
+
xhr.send(body);
|
242
|
+
}
|
243
|
+
|
244
|
+
S3MP.prototype.createXhrRequest = function() {
|
245
|
+
var xhrRequest;
|
246
|
+
|
247
|
+
// Sniff for xhr object
|
248
|
+
if (typeof XMLHttpRequest.constructor === "function") {
|
249
|
+
xhrRequest = XMLHttpRequest;
|
250
|
+
} else if (typeof XDomainRequest !== "undefined") {
|
251
|
+
xhrRequest = XDomainRequest;
|
252
|
+
} else {
|
253
|
+
xhrRequest = null; // Error out to the client (To-do)
|
254
|
+
}
|
255
|
+
|
256
|
+
return function(method, url, cb, open) { // open defaults to true
|
257
|
+
var args, xhr, open = true;
|
258
|
+
|
259
|
+
args = Array.prototype.slice.call(arguments);
|
260
|
+
if (typeof args[0] === "undefined") {
|
261
|
+
cb = null;
|
262
|
+
open = false;
|
263
|
+
}
|
264
|
+
|
265
|
+
xhr = new xhrRequest();
|
266
|
+
if (open) { // open the request unless specified otherwise
|
267
|
+
xhr.open(method, url, true);
|
268
|
+
}
|
269
|
+
xhr.onreadystatechange = cb;
|
270
|
+
|
271
|
+
return xhr;
|
272
|
+
};
|
273
|
+
|
274
|
+
}();
|
275
|
+
|
276
|
+
S3MP.prototype.sliceBlob = function() {
|
277
|
+
try {
|
278
|
+
var test_blob = new Blob();
|
279
|
+
} catch(e) {
|
280
|
+
return "Unsupported";
|
281
|
+
}
|
282
|
+
|
283
|
+
if (test_blob.slice) {
|
284
|
+
return function(blob, start, end) {
|
285
|
+
return blob.slice(start, end);
|
286
|
+
}
|
287
|
+
} else if (test_blob.mozSlice) {
|
288
|
+
return function(blob, start, end) {
|
289
|
+
return blob.mozSlice(start, end);
|
290
|
+
}
|
291
|
+
} else if (test_blob.webkitSlice) {
|
292
|
+
return function(blob, start, end) {
|
293
|
+
return blob.webkitSlice(start, end);
|
294
|
+
}
|
295
|
+
} else {
|
296
|
+
return "Unsupported";
|
297
|
+
}
|
298
|
+
}();
|
299
|
+
|
300
|
+
// utility function to return an upload object given a file
|
301
|
+
S3MP.prototype._returnUploadObj = function(key) {
|
302
|
+
var uploadObj = _.find(this.uploadList, function(uploadObj) {
|
303
|
+
return uploadObj.key === key;
|
304
|
+
});
|
305
|
+
return uploadObj;
|
306
|
+
};
|
307
|
+
|
308
|
+
// cancel a given file upload
|
309
|
+
S3MP.prototype.cancel = function(key) {
|
310
|
+
var uploadObj, i;
|
311
|
+
|
312
|
+
uploadObj = this._returnUploadObj(key);
|
313
|
+
i = _.indexOf(this.uploadList, uploadObj);
|
314
|
+
|
315
|
+
this.uploadList.splice(i,i+1);
|
316
|
+
this.onCancel();
|
317
|
+
};
|
318
|
+
|
319
|
+
// pause a given file upload
|
320
|
+
S3MP.prototype.pause = function(key) {
|
321
|
+
var uploadObj = this._returnUploadObj(key);
|
322
|
+
|
323
|
+
_.each(uploadObj.parts, function(part, key, list) {
|
324
|
+
if (part.status == "active") {
|
325
|
+
part.pause();
|
326
|
+
}
|
327
|
+
});
|
328
|
+
|
329
|
+
this.onPause();
|
330
|
+
};
|
331
|
+
|
332
|
+
// resume a given file upload
|
333
|
+
S3MP.prototype.resume = function(key) {
|
334
|
+
var uploadObj = this._returnUploadObj(key);
|
335
|
+
|
336
|
+
_.each(uploadObj.parts, function(part, key, list) {
|
337
|
+
if (part.status == "paused") {
|
338
|
+
part.activate();
|
339
|
+
}
|
340
|
+
});
|
341
|
+
|
342
|
+
this.onResume();
|
343
|
+
};
|
344
|
+
// Upload constructor
|
345
|
+
function Upload(file, o, key) {
|
346
|
+
function Upload() {
|
347
|
+
var upload, id, parts, part, segs, chunk_segs, chunk_lens, pipes, blob;
|
348
|
+
|
349
|
+
upload = this;
|
350
|
+
|
351
|
+
this.key = key;
|
352
|
+
this.file = file;
|
353
|
+
this.name = file.name;
|
354
|
+
this.size = file.size;
|
355
|
+
this.type = file.type;
|
356
|
+
this.Etags = [];
|
357
|
+
this.inprogress = [];
|
358
|
+
this.uploaded = 0;
|
359
|
+
this.status = "";
|
360
|
+
|
361
|
+
// Break the file into an appropriate amount of chunks
|
362
|
+
// This needs to be optimized for various browsers types/versions
|
363
|
+
if (this.size > 1000000000) { // size greater than 1gb
|
364
|
+
num_segs = 100;
|
365
|
+
pipes = 10;
|
366
|
+
} else if (this.size > 500000000) { // greater than 500mb
|
367
|
+
num_segs = 50;
|
368
|
+
pipes = 5;
|
369
|
+
} else if (this.size > 100000000) { // greater than 100 mb
|
370
|
+
num_segs = 20;
|
371
|
+
pipes = 5;
|
372
|
+
} else if (this.size > 5000000) { // greater than 5 mb (S3 does not allow multipart uploads < 5 mb)
|
373
|
+
num_segs = 2;
|
374
|
+
pipes = 2;
|
375
|
+
} else {
|
376
|
+
num_segs = 10;
|
377
|
+
pipes = 3;
|
378
|
+
}
|
379
|
+
|
380
|
+
chunk_segs = _.range(num_segs + 1);
|
381
|
+
chunk_lens = _.map(chunk_segs, function(seg) {
|
382
|
+
return Math.round(seg * (file.size/num_segs));
|
383
|
+
});
|
384
|
+
|
385
|
+
this.parts = _.map(chunk_lens, function(len, i) {
|
386
|
+
blob = upload.sliceBlob(file, len, chunk_lens[i+1]);
|
387
|
+
return new UploadPart(blob, i+1, upload);
|
388
|
+
});
|
389
|
+
|
390
|
+
this.parts.pop(); // Remove the empty blob at the end of the array
|
391
|
+
|
392
|
+
// init function will initiate the multipart upload, sign all the parts, and
|
393
|
+
// start uploading some parts in parallel
|
394
|
+
this.init = function() {
|
395
|
+
upload.initiateMultipart(upload, function(obj) {
|
396
|
+
var id = upload.id = obj.id
|
397
|
+
, upload_id = upload.upload_id = obj.upload_id
|
398
|
+
, object_name = upload.object_name = obj.key // uuid generated by the server, different from name
|
399
|
+
, parts = upload.parts;
|
400
|
+
|
401
|
+
upload.signPartRequests(id, object_name, upload_id, parts, function(response) {
|
402
|
+
_.each(parts, function(part, key) {
|
403
|
+
var xhr = part.xhr;
|
404
|
+
|
405
|
+
xhr.open('PUT', 'http://'+upload.bucket+'.s3.amazonaws.com/'+object_name+'?partNumber='+part.num+'&uploadId='+upload_id, true);
|
406
|
+
xhr.setRequestHeader('x-amz-date', response[key].date);
|
407
|
+
xhr.setRequestHeader('Authorization', response[key].authorization);
|
408
|
+
|
409
|
+
// Notify handler that an xhr request has been opened
|
410
|
+
upload.handler.beginUpload(pipes, upload);
|
411
|
+
});
|
412
|
+
});
|
413
|
+
});
|
414
|
+
}
|
415
|
+
};
|
416
|
+
// Inherit the properties and prototype methods of the passed in S3MP instance object
|
417
|
+
Upload.prototype = o;
|
418
|
+
return new Upload();
|
419
|
+
}
|
420
|
+
// Upload part constructor
|
421
|
+
function UploadPart(blob, key, upload) {
|
422
|
+
var part, xhr;
|
423
|
+
|
424
|
+
part = this;
|
425
|
+
|
426
|
+
this.size = blob.size;
|
427
|
+
this.blob = blob;
|
428
|
+
this.num = key;
|
429
|
+
|
430
|
+
this.xhr = xhr = upload.createXhrRequest();
|
431
|
+
xhr.onload = function() {
|
432
|
+
upload.handler.onPartSuccess(upload, part);
|
433
|
+
};
|
434
|
+
xhr.onerror = function() {
|
435
|
+
upload.handler.onError(upload, part);
|
436
|
+
};
|
437
|
+
xhr.upload.onprogress = _.throttle(function(e) {
|
438
|
+
upload.inprogress[key] = e.loaded;
|
439
|
+
}, 1000);
|
440
|
+
|
441
|
+
};
|
442
|
+
|
443
|
+
UploadPart.prototype.activate = function() {
|
444
|
+
this.xhr.send(this.blob);
|
445
|
+
this.status = "active";
|
446
|
+
};
|
447
|
+
|
448
|
+
UploadPart.prototype.pause = function() {
|
449
|
+
this.xhr.abort();
|
450
|
+
this.status = "paused";
|
451
|
+
};
|
452
|
+
return S3MP;
|
453
|
+
|
454
|
+
}());
|
455
|
+
|
456
|
+
}(this));
|
@@ -0,0 +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>5e6?(num_segs=2,l=2):(num_segs=10,l=3),a=_.range(num_segs+1),f=_.map(a,function(t){return Math.round(t*(e.size/num_segs))}),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]=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,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);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: s3_multipart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: uuid
|
@@ -144,10 +144,10 @@ email:
|
|
144
144
|
- max.gillett@gmail.com
|
145
145
|
executables: []
|
146
146
|
extensions: []
|
147
|
-
extra_rdoc_files:
|
147
|
+
extra_rdoc_files:
|
148
|
+
- README.md
|
148
149
|
files:
|
149
150
|
- .gitignore
|
150
|
-
- .rspec
|
151
151
|
- Gemfile
|
152
152
|
- Gemfile.lock
|
153
153
|
- LICENSE.txt
|
@@ -157,35 +157,126 @@ files:
|
|
157
157
|
- app/controllers/s3_multipart/uploads_controller.rb
|
158
158
|
- app/models/s3_multipart/upload.rb
|
159
159
|
- config/routes.rb
|
160
|
-
-
|
160
|
+
- grunt.js
|
161
|
+
- javascripts/footer.js
|
162
|
+
- javascripts/header.js
|
163
|
+
- javascripts/libs/underscore.js
|
164
|
+
- javascripts/s3mp.js
|
165
|
+
- javascripts/upload.js
|
166
|
+
- javascripts/uploadpart.js
|
167
|
+
- lib/generators/s3_multipart/install_generator.rb
|
168
|
+
- lib/generators/s3_multipart/templates/add_uploader_column_to_model.rb
|
169
|
+
- lib/generators/s3_multipart/templates/aws.yml
|
170
|
+
- lib/generators/s3_multipart/templates/configuration_initializer.rb
|
171
|
+
- lib/generators/s3_multipart/templates/uploader.rb
|
172
|
+
- lib/generators/s3_multipart/templates/uploads_table_migration.rb
|
173
|
+
- lib/generators/s3_multipart/uploader_generator.rb
|
161
174
|
- lib/s3_multipart.rb
|
162
175
|
- lib/s3_multipart/action_view_helpers/form_helper.rb
|
176
|
+
- lib/s3_multipart/config.rb
|
163
177
|
- lib/s3_multipart/engine.rb
|
164
178
|
- lib/s3_multipart/http/net_http.rb
|
165
179
|
- lib/s3_multipart/railtie.rb
|
180
|
+
- lib/s3_multipart/transfer_helpers.rb
|
166
181
|
- lib/s3_multipart/uploader.rb
|
167
|
-
- lib/s3_multipart/uploader/
|
182
|
+
- lib/s3_multipart/uploader/callbacks.rb
|
183
|
+
- lib/s3_multipart/uploader/validations.rb
|
168
184
|
- lib/s3_multipart/version.rb
|
185
|
+
- package.json
|
169
186
|
- s3_multipart.gemspec
|
170
187
|
- spec/integration/uploads_controller_spec.rb
|
171
188
|
- spec/internal/app/assets/javascripts/application.js
|
172
189
|
- spec/internal/app/assets/javascripts/jquery.js
|
173
190
|
- spec/internal/app/assets/javascripts/underscore.js
|
174
|
-
- spec/internal/app/assets/stylesheets/application.css
|
191
|
+
- spec/internal/app/assets/stylesheets/application.css.scss
|
192
|
+
- spec/internal/app/assets/stylesheets/font-awesome.scss
|
175
193
|
- spec/internal/app/controllers/application_controller.rb
|
176
194
|
- spec/internal/app/controllers/pages_controller.rb
|
195
|
+
- spec/internal/app/models/user.rb
|
196
|
+
- spec/internal/app/models/video.rb
|
197
|
+
- spec/internal/app/uploaders/multipart/video_uploader.rb
|
177
198
|
- spec/internal/app/views/layouts/application.html.erb
|
178
199
|
- spec/internal/app/views/pages/upload.html.erb
|
179
200
|
- spec/internal/config/database.yml
|
180
201
|
- spec/internal/config/routes.rb
|
181
|
-
- spec/internal/db/combustion_test.sqlite3
|
182
202
|
- spec/internal/db/schema.rb
|
183
203
|
- spec/internal/log/.gitignore
|
184
204
|
- spec/internal/public/favicon.ico
|
185
|
-
- spec/
|
205
|
+
- spec/internal/public/fonts/FontAwesome.otf
|
206
|
+
- spec/internal/public/fonts/fontawesome-webfont.eot
|
207
|
+
- spec/internal/public/fonts/fontawesome-webfont.ttf
|
208
|
+
- spec/internal/public/fonts/fontawesome-webfont.woff
|
209
|
+
- spec/internal/tmp/cache/sass/077f66d4d9153cfd737b81ab3f4c5d5858b0db3b/_grid-background.scssc
|
210
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_appearance.scssc
|
211
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_background-clip.scssc
|
212
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_background-origin.scssc
|
213
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_background-size.scssc
|
214
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_border-radius.scssc
|
215
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_box-shadow.scssc
|
216
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_box-sizing.scssc
|
217
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_box.scssc
|
218
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_columns.scssc
|
219
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_filter.scssc
|
220
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_font-face.scssc
|
221
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_hyphenation.scssc
|
222
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_images.scssc
|
223
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_inline-block.scssc
|
224
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_opacity.scssc
|
225
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_regions.scssc
|
226
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_shared.scssc
|
227
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_text-shadow.scssc
|
228
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_transform.scssc
|
229
|
+
- spec/internal/tmp/cache/sass/1925334270d3f17f5ea2c4e86092ee0214484038/_transition.scssc
|
230
|
+
- spec/internal/tmp/cache/sass/351072894b53bf1a2d2af4bd57c177c805cf063e/_contrast.scssc
|
231
|
+
- spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_css3.scssc
|
232
|
+
- spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_support.scssc
|
233
|
+
- spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_typography.scssc
|
234
|
+
- spec/internal/tmp/cache/sass/49ecd6d86aba13e15e515be708bbfd8bb67a011a/_utilities.scssc
|
235
|
+
- spec/internal/tmp/cache/sass/633bc5f017268b81a60f921876c980c4adcebb74/_base.scssc
|
236
|
+
- spec/internal/tmp/cache/sass/633bc5f017268b81a60f921876c980c4adcebb74/_sprite-img.scssc
|
237
|
+
- spec/internal/tmp/cache/sass/68dbce8ac3037e0cd797c9b5c6aa131096361144/_utilities.scssc
|
238
|
+
- spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_clearfix.scssc
|
239
|
+
- spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_float.scssc
|
240
|
+
- spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_hacks.scssc
|
241
|
+
- spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_min.scssc
|
242
|
+
- spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_reset.scssc
|
243
|
+
- spec/internal/tmp/cache/sass/7722315031801f2a146090aa73380dfd28539145/_tag-cloud.scssc
|
244
|
+
- spec/internal/tmp/cache/sass/775792c99f07f64e98296a8dc8c9d2c74a28fd8a/_reset.scssc
|
245
|
+
- spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_ellipsis.scssc
|
246
|
+
- spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_force-wrap.scssc
|
247
|
+
- spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_nowrap.scssc
|
248
|
+
- spec/internal/tmp/cache/sass/8b4f1545a124f2498699911561d1ec6302c9de56/_replacement.scssc
|
249
|
+
- spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_bullets.scssc
|
250
|
+
- spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_horizontal-list.scssc
|
251
|
+
- spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_inline-block-list.scssc
|
252
|
+
- spec/internal/tmp/cache/sass/abd68615441476dbd8e9fdc1606210305b3177fd/_inline-list.scssc
|
253
|
+
- spec/internal/tmp/cache/sass/b1bb3e2fbcb5c6a71ea2273c6dcb7c8967d2a058/_alternating-rows-and-columns.scssc
|
254
|
+
- spec/internal/tmp/cache/sass/b1bb3e2fbcb5c6a71ea2273c6dcb7c8967d2a058/_borders.scssc
|
255
|
+
- spec/internal/tmp/cache/sass/b1bb3e2fbcb5c6a71ea2273c6dcb7c8967d2a058/_scaffolding.scssc
|
256
|
+
- spec/internal/tmp/cache/sass/bc7f11d6e8f07a22f545deb35760cfc7830f3369/application.css.scssc
|
257
|
+
- spec/internal/tmp/cache/sass/bc7f11d6e8f07a22f545deb35760cfc7830f3369/font-awesome.scssc
|
258
|
+
- spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_color.scssc
|
259
|
+
- spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_general.scssc
|
260
|
+
- spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_sprites.scssc
|
261
|
+
- spec/internal/tmp/cache/sass/c9342b40bf8bc7bf64ce587860fb065cbf6d2ca4/_tables.scssc
|
262
|
+
- spec/internal/tmp/cache/sass/d1da036a47062a9f69ce0327962c00aa77d2ea44/_hover-link.scssc
|
263
|
+
- spec/internal/tmp/cache/sass/d1da036a47062a9f69ce0327962c00aa77d2ea44/_link-colors.scssc
|
264
|
+
- spec/internal/tmp/cache/sass/d1da036a47062a9f69ce0327962c00aa77d2ea44/_unstyled-link.scssc
|
265
|
+
- spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_links.scssc
|
266
|
+
- spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_lists.scssc
|
267
|
+
- spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_text.scssc
|
268
|
+
- spec/internal/tmp/cache/sass/d559b7bf0c5e0c0d23f2f34bfc21b4817fb38463/_vertical_rhythm.scssc
|
269
|
+
- spec/internal/tmp/cache/sass/e2e5b9bb57a9d1b018b9f546bc8b16f6b2a627a9/_compass.scssc
|
270
|
+
- spec/internal/tmp/cache/sass/e654955d4502954a409bf21071c0d98eb4ac2e9f/_utilities.scssc
|
271
|
+
- spec/javascripts/UploadSpec.js
|
272
|
+
- spec/javascripts/helpers/SpecHelper.js
|
273
|
+
- spec/javascripts/support/jasmine.yml
|
186
274
|
- spec/spec_helper.rb
|
187
|
-
-
|
188
|
-
-
|
275
|
+
- spec/unit/upload_controller_spec.rb
|
276
|
+
- spec/unit/upload_spec.rb
|
277
|
+
- spec/unit/uploader_module_spec.rb
|
278
|
+
- vendor/assets/javascripts/s3_multipart/lib.js
|
279
|
+
- vendor/assets/javascripts/s3_multipart/lib.min.js
|
189
280
|
homepage: https://github.com/maxgillett/s3_multipart
|
190
281
|
licenses: []
|
191
282
|
post_install_message:
|
@@ -206,7 +297,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
297
|
version: '0'
|
207
298
|
requirements: []
|
208
299
|
rubyforge_project:
|
209
|
-
rubygems_version: 1.8.
|
300
|
+
rubygems_version: 1.8.25
|
210
301
|
signing_key:
|
211
302
|
specification_version: 3
|
212
303
|
summary: Upload directly to S3 using multipart uploading
|
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|
File without changes
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
//=require s3_multipart
|