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