UNPKG

20.5 kBJavaScriptView Raw
1(function() {
2 var Chunkable, EncodeFieldPart, EncodeFilePart, Q, TEXT_PARAMS, UploadStream, Writable, _, build_upload_params, call_api, call_context_api, call_tags_api, config, fs, https, path, post, util, utils,
3 extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
4 hasProp = {}.hasOwnProperty;
5
6 _ = require("lodash");
7
8 config = require("./config");
9
10 if (config().upload_prefix && config().upload_prefix.slice(0, 5) === 'http:') {
11 https = require('http');
12 } else {
13 https = require('https');
14 }
15
16 UploadStream = require('./upload_stream');
17
18 utils = require("./utils");
19
20 util = require("util");
21
22 fs = require('fs');
23
24 path = require('path');
25
26 Q = require('q');
27
28 Writable = require("stream").Writable;
29
30 build_upload_params = function(options) {
31 return utils.build_upload_params(options);
32 };
33
34 exports.unsigned_upload_stream = function(upload_preset, callback, options) {
35 if (options == null) {
36 options = {};
37 }
38 return exports.upload_stream(callback, utils.merge(options, {
39 unsigned: true,
40 upload_preset: upload_preset
41 }));
42 };
43
44 exports.upload_stream = function(callback, options) {
45 if (options == null) {
46 options = {};
47 }
48 return exports.upload(null, callback, _.extend({
49 stream: true
50 }, options));
51 };
52
53 exports.unsigned_upload = function(file, upload_preset, callback, options) {
54 if (options == null) {
55 options = {};
56 }
57 return exports.upload(file, callback, utils.merge(options, {
58 unsigned: true,
59 upload_preset: upload_preset
60 }));
61 };
62
63 exports.upload = function(file, callback, options) {
64 if (options == null) {
65 options = {};
66 }
67 return call_api("upload", callback, options, function() {
68 var params;
69 params = build_upload_params(options);
70 if ((file != null) && file.match(/^ftp:|^https?:|^s3:|^data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$/)) {
71 return [
72 params, {
73 file: file
74 }
75 ];
76 } else {
77 return [params, {}, file];
78 }
79 });
80 };
81
82 exports.upload_large = function(path, callback, options) {
83 if (options == null) {
84 options = {};
85 }
86 if ((path != null) && path.match(/^https?:/)) {
87 return exports.upload(path, callback, options);
88 } else {
89 return exports.upload_chunked(path, callback, _.extend({
90 resource_type: 'raw'
91 }, options));
92 }
93 };
94
95 exports.upload_chunked = function(path, callback, options) {
96 var file_reader, out_stream;
97 file_reader = fs.createReadStream(path);
98 out_stream = exports.upload_chunked_stream(callback, options);
99 return file_reader.pipe(out_stream);
100 };
101
102 Chunkable = (function(superClass) {
103 extend(Chunkable, superClass);
104
105 function Chunkable(options) {
106 var ref;
107 this.chunk_size = (ref = options.chunk_size) != null ? ref : 20000000;
108 this.buffer = new Buffer(0);
109 this.active = true;
110 Chunkable.__super__.constructor.call(this, options);
111 this.on('finish', (function(_this) {
112 return function() {
113 if (_this.active) {
114 return _this.emit('ready', _this.buffer, true, function() {});
115 }
116 };
117 })(this));
118 }
119
120 Chunkable.prototype._write = function(data, encoding, done) {
121 var grab;
122 if (!this.active) {
123 return done();
124 }
125 if (this.buffer.length + data.length <= this.chunk_size) {
126 this.buffer = Buffer.concat([this.buffer, data], this.buffer.length + data.length);
127 return done();
128 } else {
129 grab = this.chunk_size - this.buffer.length;
130 this.buffer = Buffer.concat([this.buffer, data.slice(0, grab)], this.buffer.length + grab);
131 return this.emit('ready', this.buffer, false, (function(_this) {
132 return function(active) {
133 _this.active = active;
134 if (_this.active) {
135 _this.buffer = data.slice(grab);
136 return done();
137 }
138 };
139 })(this));
140 }
141 };
142
143 return Chunkable;
144
145 })(Writable);
146
147 exports.upload_large_stream = function(_unused_, callback, options) {
148 if (options == null) {
149 options = {};
150 }
151 return exports.upload_chunked_stream(callback, _.extend({
152 resource_type: 'raw'
153 }, options));
154 };
155
156 exports.upload_chunked_stream = function(callback, options) {
157 var chunk_size, chunker, params, ref, sent;
158 if (options == null) {
159 options = {};
160 }
161 options = _.extend({}, options, {
162 stream: true
163 });
164 options.x_unique_upload_id = utils.random_public_id();
165 params = build_upload_params(options);
166 chunk_size = (ref = options.chunk_size) != null ? ref : options.part_size;
167 chunker = new Chunkable({
168 chunk_size: chunk_size
169 });
170 sent = 0;
171 chunker.on('ready', function(buffer, is_last, done) {
172 var chunk_start, finished_part, stream;
173 chunk_start = sent;
174 sent += buffer.length;
175 options.content_range = util.format("bytes %d-%d/%d", chunk_start, sent - 1, is_last ? sent : -1);
176 finished_part = function(result) {
177 if ((result.error != null) || is_last) {
178 if (typeof callback === "function") {
179 callback(result);
180 }
181 return done(false);
182 } else {
183 return done(true);
184 }
185 };
186 stream = call_api("upload", finished_part, options, function() {
187 return [params, {}, buffer];
188 });
189 return stream.write(buffer, 'buffer', function() {
190 return stream.end();
191 });
192 });
193 return chunker;
194 };
195
196 exports.explicit = function(public_id, callback, options) {
197 if (options == null) {
198 options = {};
199 }
200 return call_api("explicit", callback, options, function() {
201 return utils.build_explicit_api_params(public_id, options);
202 });
203 };
204
205 exports.create_archive = function(callback, options, target_format) {
206 if (options == null) {
207 options = {};
208 }
209 if (target_format == null) {
210 target_format = null;
211 }
212 return call_api("generate_archive", callback, options, function() {
213 var opt;
214 opt = utils.archive_params(options);
215 if (target_format) {
216 opt.target_format = target_format;
217 }
218 return [opt];
219 });
220 };
221
222 exports.create_zip = function(callback, options) {
223 if (options == null) {
224 options = {};
225 }
226 return exports.create_archive(callback, options, "zip");
227 };
228
229 exports.destroy = function(public_id, callback, options) {
230 if (options == null) {
231 options = {};
232 }
233 return call_api("destroy", callback, options, function() {
234 return [
235 {
236 timestamp: utils.timestamp(),
237 type: options.type,
238 invalidate: options.invalidate,
239 public_id: public_id
240 }
241 ];
242 });
243 };
244
245 exports.rename = function(from_public_id, to_public_id, callback, options) {
246 if (options == null) {
247 options = {};
248 }
249 return call_api("rename", callback, options, function() {
250 return [
251 {
252 timestamp: utils.timestamp(),
253 type: options.type,
254 from_public_id: from_public_id,
255 to_public_id: to_public_id,
256 overwrite: options.overwrite,
257 invalidate: options.invalidate,
258 to_type: options.to_type
259 }
260 ];
261 });
262 };
263
264 TEXT_PARAMS = ["public_id", "font_family", "font_size", "font_color", "text_align", "font_weight", "font_style", "background", "opacity", "text_decoration"];
265
266 exports.text = function(text, callback, options) {
267 if (options == null) {
268 options = {};
269 }
270 return call_api("text", callback, options, function() {
271 var j, k, len, params;
272 params = {
273 timestamp: utils.timestamp(),
274 text: text
275 };
276 for (j = 0, len = TEXT_PARAMS.length; j < len; j++) {
277 k = TEXT_PARAMS[j];
278 if (options[k] != null) {
279 params[k] = options[k];
280 }
281 }
282 return [params];
283 });
284 };
285
286 exports.generate_sprite = function(tag, callback, options) {
287 if (options == null) {
288 options = {};
289 }
290 return call_api("sprite", callback, options, function() {
291 var transformation;
292 transformation = utils.generate_transformation_string(_.extend({}, options, {
293 fetch_format: options.format
294 }));
295 return [
296 {
297 timestamp: utils.timestamp(),
298 tag: tag,
299 transformation: transformation,
300 async: options.async,
301 notification_url: options.notification_url
302 }
303 ];
304 });
305 };
306
307 exports.multi = function(tag, callback, options) {
308 if (options == null) {
309 options = {};
310 }
311 return call_api("multi", callback, options, function() {
312 var transformation;
313 transformation = utils.generate_transformation_string(_.extend({}, options));
314 return [
315 {
316 timestamp: utils.timestamp(),
317 tag: tag,
318 transformation: transformation,
319 format: options.format,
320 async: options.async,
321 notification_url: options.notification_url
322 }
323 ];
324 });
325 };
326
327 exports.explode = function(public_id, callback, options) {
328 if (options == null) {
329 options = {};
330 }
331 return call_api("explode", callback, options, function() {
332 var transformation;
333 transformation = utils.generate_transformation_string(_.extend({}, options));
334 return [
335 {
336 timestamp: utils.timestamp(),
337 public_id: public_id,
338 transformation: transformation,
339 format: options.format,
340 type: options.type,
341 notification_url: options.notification_url
342 }
343 ];
344 });
345 };
346
347 exports.add_tag = function(tag, public_ids, callback, options) {
348 var command, exclusive;
349 if (public_ids == null) {
350 public_ids = [];
351 }
352 if (options == null) {
353 options = {};
354 }
355 exclusive = utils.option_consume("exclusive", options);
356 command = exclusive ? "set_exclusive" : "add";
357 return call_tags_api(tag, command, public_ids, callback, options);
358 };
359
360 exports.remove_tag = function(tag, public_ids, callback, options) {
361 if (public_ids == null) {
362 public_ids = [];
363 }
364 if (options == null) {
365 options = {};
366 }
367 return call_tags_api(tag, "remove", public_ids, callback, options);
368 };
369
370 exports.remove_all_tags = function(public_ids, callback, options) {
371 if (public_ids == null) {
372 public_ids = [];
373 }
374 if (options == null) {
375 options = {};
376 }
377 return call_tags_api(null, "remove_all", public_ids, callback, options);
378 };
379
380 exports.replace_tag = function(tag, public_ids, callback, options) {
381 if (public_ids == null) {
382 public_ids = [];
383 }
384 if (options == null) {
385 options = {};
386 }
387 return call_tags_api(tag, "replace", public_ids, callback, options);
388 };
389
390 call_tags_api = function(tag, command, public_ids, callback, options) {
391 if (public_ids == null) {
392 public_ids = [];
393 }
394 if (options == null) {
395 options = {};
396 }
397 return call_api("tags", callback, options, function() {
398 var params;
399 params = {
400 timestamp: utils.timestamp(),
401 public_ids: utils.build_array(public_ids),
402 command: command,
403 type: options.type
404 };
405 if (tag != null) {
406 params.tag = tag;
407 }
408 return [params];
409 });
410 };
411
412 exports.add_context = function(context, public_ids, callback, options) {
413 if (public_ids == null) {
414 public_ids = [];
415 }
416 if (options == null) {
417 options = {};
418 }
419 return call_context_api(context, 'add', public_ids, callback, options);
420 };
421
422 exports.remove_all_context = function(public_ids, callback, options) {
423 if (public_ids == null) {
424 public_ids = [];
425 }
426 if (options == null) {
427 options = {};
428 }
429 return call_context_api(null, 'remove_all', public_ids, callback, options);
430 };
431
432 call_context_api = function(context, command, public_ids, callback, options) {
433 if (public_ids == null) {
434 public_ids = [];
435 }
436 if (options == null) {
437 options = {};
438 }
439 return call_api('context', callback, options, function() {
440 var params;
441 params = {
442 timestamp: utils.timestamp(),
443 public_ids: utils.build_array(public_ids),
444 command: command,
445 type: options.type
446 };
447 if (context != null) {
448 params.context = utils.encode_context(context);
449 }
450 return [params];
451 });
452 };
453
454 call_api = function(action, callback, options, get_params) {
455 var api_url, boundary, deferred, error, file, handle_response, j, key, len, params, post_data, ref, result, unsigned_params, v, value;
456 deferred = Q.defer();
457 if (options == null) {
458 options = {};
459 }
460 ref = get_params.call(), params = ref[0], unsigned_params = ref[1], file = ref[2];
461 params = utils.process_request_params(params, options);
462 params = _.extend(params, unsigned_params);
463 api_url = utils.api_url(action, options);
464 boundary = utils.random_public_id();
465 error = false;
466 handle_response = function(res) {
467 var buffer, error_obj;
468 if (error) {
469
470 } else if (res.error) {
471 error = true;
472 deferred.reject(res);
473 return typeof callback === "function" ? callback(res) : void 0;
474 } else if (_.includes([200, 400, 401, 404, 420, 500], res.statusCode)) {
475 buffer = "";
476 res.on("data", function(d) {
477 return buffer += d;
478 });
479 res.on("end", function() {
480 var e, result;
481 if (error) {
482 return;
483 }
484 try {
485 result = JSON.parse(buffer);
486 } catch (error1) {
487 e = error1;
488 result = {
489 error: {
490 message: "Server return invalid JSON response. Status Code " + res.statusCode
491 }
492 };
493 }
494 if (result["error"]) {
495 result["error"]["http_code"] = res.statusCode;
496 }
497 if (result.error) {
498 deferred.reject(result.error);
499 } else {
500 deferred.resolve(result);
501 }
502 return typeof callback === "function" ? callback(result) : void 0;
503 });
504 return res.on("error", function(e) {
505 error = true;
506 deferred.reject(e);
507 return typeof callback === "function" ? callback({
508 error: e
509 }) : void 0;
510 });
511 } else {
512 error_obj = {
513 error: {
514 message: "Server returned unexpected status code - " + res.statusCode,
515 http_code: res.statusCode
516 }
517 };
518 deferred.reject(error_obj.error);
519 return typeof callback === "function" ? callback(error_obj) : void 0;
520 }
521 };
522 post_data = [];
523 for (key in params) {
524 value = params[key];
525 if (_.isArray(value)) {
526 for (j = 0, len = value.length; j < len; j++) {
527 v = value[j];
528 post_data.push(new Buffer(EncodeFieldPart(boundary, key + "[]", v), 'utf8'));
529 }
530 } else if (utils.present(value)) {
531 post_data.push(new Buffer(EncodeFieldPart(boundary, key, value), 'utf8'));
532 }
533 }
534 result = post(api_url, post_data, boundary, file, handle_response, options);
535 if (_.isObject(result)) {
536 return result;
537 } else {
538 return deferred.promise;
539 }
540 };
541
542 post = function(url, post_data, boundary, file, callback, options) {
543 var file_header, filename, finish_buffer, headers, i, j, post_options, post_request, ref, ref1, timeout, upload_stream;
544 finish_buffer = new Buffer("--" + boundary + "--", 'ascii');
545 if ((file != null) || options.stream) {
546 filename = options.stream ? "file" : path.basename(file);
547 file_header = new Buffer(EncodeFilePart(boundary, 'application/octet-stream', 'file', filename), 'binary');
548 }
549 post_options = require('url').parse(url);
550 headers = {
551 'Content-Type': 'multipart/form-data; boundary=' + boundary,
552 'User-Agent': utils.getUserAgent()
553 };
554 if (options.content_range != null) {
555 headers['Content-Range'] = options.content_range;
556 }
557 if (options.x_unique_upload_id != null) {
558 headers['X-Unique-Upload-Id'] = options.x_unique_upload_id;
559 }
560 post_options = _.extend(post_options, {
561 method: 'POST',
562 headers: headers
563 });
564 if (options.agent != null) {
565 post_options.agent = options.agent;
566 }
567 post_request = https.request(post_options, callback);
568 upload_stream = new UploadStream({
569 boundary: boundary
570 });
571 upload_stream.pipe(post_request);
572 timeout = false;
573 post_request.on("error", function(e) {
574 if (timeout) {
575 return callback({
576 error: {
577 message: "Request Timeout",
578 http_code: 499
579 }
580 });
581 } else {
582 return callback({
583 error: e
584 });
585 }
586 });
587 post_request.setTimeout((ref = options.timeout) != null ? ref : 60000, function() {
588 timeout = true;
589 return post_request.abort();
590 });
591 for (i = j = 0, ref1 = post_data.length - 1; 0 <= ref1 ? j <= ref1 : j >= ref1; i = 0 <= ref1 ? ++j : --j) {
592 post_request.write(post_data[i]);
593 }
594 if (options.stream) {
595 post_request.write(file_header);
596 return upload_stream;
597 } else if (file != null) {
598 post_request.write(file_header);
599 fs.createReadStream(file).on('error', function(error) {
600 callback({
601 error: error
602 });
603 return post_request.abort();
604 }).pipe(upload_stream);
605 } else {
606 post_request.write(finish_buffer);
607 post_request.end();
608 }
609 return true;
610 };
611
612 EncodeFieldPart = function(boundary, name, value) {
613 var return_part;
614 return_part = "--" + boundary + "\r\n";
615 return_part += "Content-Disposition: form-data; name=\"" + name + "\"\r\n\r\n";
616 return_part += value + "\r\n";
617 return return_part;
618 };
619
620 EncodeFilePart = function(boundary, type, name, filename) {
621 var return_part;
622 return_part = "--" + boundary + "\r\n";
623 return_part += "Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n";
624 return_part += "Content-Type: " + type + "\r\n\r\n";
625 return return_part;
626 };
627
628 exports.direct_upload = function(callback_url, options) {
629 var api_url, params;
630 if (options == null) {
631 options = {};
632 }
633 params = build_upload_params(_.extend({
634 callback: callback_url
635 }, options));
636 params = utils.process_request_params(params, options);
637 api_url = utils.api_url("upload", options);
638 return {
639 hidden_fields: params,
640 form_attrs: {
641 action: api_url,
642 method: "POST",
643 enctype: "multipart/form-data"
644 }
645 };
646 };
647
648 exports.upload_tag_params = function(options) {
649 var params;
650 if (options == null) {
651 options = {};
652 }
653 params = build_upload_params(options);
654 params = utils.process_request_params(params, options);
655 return JSON.stringify(params);
656 };
657
658 exports.upload_url = function(options) {
659 if (options == null) {
660 options = {};
661 }
662 if (options.resource_type == null) {
663 options.resource_type = "auto";
664 }
665 return utils.api_url("upload", options);
666 };
667
668 exports.image_upload_tag = function(field, options) {
669 var html_options, ref, tag_options;
670 if (options == null) {
671 options = {};
672 }
673 html_options = (ref = options.html) != null ? ref : {};
674 tag_options = _.extend({
675 type: "file",
676 name: "file",
677 "data-url": exports.upload_url(options),
678 "data-form-data": exports.upload_tag_params(options),
679 "data-cloudinary-field": field,
680 "data-max-chunk-size": options.chunk_size,
681 "class": [html_options["class"], "cloudinary-fileupload"].join(" ")
682 }, html_options);
683 return '<input ' + utils.html_attrs(tag_options) + '/>';
684 };
685
686 exports.unsigned_image_upload_tag = function(field, upload_preset, options) {
687 if (options == null) {
688 options = {};
689 }
690 return exports.image_upload_tag(field, utils.merge(options, {
691 unsigned: true,
692 upload_preset: upload_preset
693 }));
694 };
695
696}).call(this);
697
698//# sourceMappingURL=uploader.js.map