You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
3.8 KiB
211 lines
3.8 KiB
'use strict'; |
|
var path = require('path'); |
|
var url = require('url'); |
|
var caw = require('caw'); |
|
var concatStream = require('concat-stream'); |
|
var decompress = require('gulp-decompress'); |
|
var eachAsync = require('each-async'); |
|
var filenamify = require('filenamify'); |
|
var got = require('got'); |
|
var isUrl = require('is-url'); |
|
var objectAssign = require('object-assign'); |
|
var readAllStream = require('read-all-stream'); |
|
var rename = require('gulp-rename'); |
|
var streamCombiner = require('stream-combiner2'); |
|
var PassThrough = require('readable-stream/passthrough'); |
|
var Vinyl = require('vinyl'); |
|
var vinylFs = require('vinyl-fs'); |
|
var Ware = require('ware'); |
|
|
|
/** |
|
* Initialize a new `Download` |
|
* |
|
* @param {Object} opts |
|
* @api public |
|
*/ |
|
|
|
function Download(opts) { |
|
if (!(this instanceof Download)) { |
|
return new Download(opts); |
|
} |
|
|
|
this.opts = objectAssign({encoding: null}, opts); |
|
this.ware = new Ware(); |
|
} |
|
|
|
module.exports = Download; |
|
|
|
/** |
|
* Get or set URL to download |
|
* |
|
* @param {String} url |
|
* @param {String} dest |
|
* @api public |
|
*/ |
|
|
|
Download.prototype.get = function (url, dest) { |
|
if (!arguments.length) { |
|
return this._get; |
|
} |
|
|
|
this._get = this._get || []; |
|
this._get.push({ |
|
url: url, |
|
dest: dest |
|
}); |
|
|
|
return this; |
|
}; |
|
|
|
/** |
|
* Get or set the destination folder |
|
* |
|
* @param {String} dir |
|
* @api public |
|
*/ |
|
|
|
Download.prototype.dest = function (dir) { |
|
if (!arguments.length) { |
|
return this._dest; |
|
} |
|
|
|
this._dest = dir; |
|
return this; |
|
}; |
|
|
|
/** |
|
* Rename the downloaded file |
|
* |
|
* @param {Function|String} name |
|
* @api public |
|
*/ |
|
|
|
Download.prototype.rename = function (name) { |
|
if (!arguments.length) { |
|
return this._rename; |
|
} |
|
|
|
this._rename = name; |
|
return this; |
|
}; |
|
|
|
/** |
|
* Add a plugin to the middleware stack |
|
* |
|
* @param {Function} plugin |
|
* @api public |
|
*/ |
|
|
|
Download.prototype.use = function (plugin) { |
|
this.ware.use(plugin); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Run |
|
* |
|
* @param {Function} cb |
|
* @api public |
|
*/ |
|
|
|
Download.prototype.run = function (cb) { |
|
cb = cb || function () {}; |
|
var files = []; |
|
|
|
eachAsync(this.get(), function (get, i, done) { |
|
if (!isUrl(get.url)) { |
|
done(new Error('Specify a valid URL')); |
|
return; |
|
} |
|
|
|
var protocol = url.parse(get.url).protocol; |
|
if (protocol) { |
|
protocol = protocol.slice(0, -1); |
|
} |
|
var agent = caw(this.opts.proxy, {protocol: protocol}); |
|
var stream = got.stream(get.url, objectAssign(this.opts, {agent: agent})); |
|
|
|
stream.on('response', function (res) { |
|
stream.headers = res.headers; |
|
stream.statusCode = res.statusCode; |
|
this.ware.run(stream, get.url); |
|
}.bind(this)); |
|
|
|
var hasHttpError = false; |
|
|
|
readAllStream(stream, null, function (err, data) { |
|
if (hasHttpError) { |
|
return; |
|
} |
|
|
|
if (err) { |
|
if (err instanceof got.HTTPError) { |
|
hasHttpError = true; |
|
} |
|
|
|
done(err); |
|
return; |
|
} |
|
|
|
var dest = get.dest || this.dest(); |
|
var fileStream = this.createStream(this.createFile(get.url, data), dest); |
|
|
|
fileStream.on('error', done); |
|
fileStream.pipe(concatStream({encoding: 'object'}, function (items) { |
|
files = files.concat(items); |
|
done(); |
|
})); |
|
}.bind(this)); |
|
}.bind(this), function (err) { |
|
if (err) { |
|
cb(err); |
|
return; |
|
} |
|
|
|
cb(null, files); |
|
}); |
|
}; |
|
|
|
/** |
|
* Create vinyl file |
|
* |
|
* @param {String} url |
|
* @param {Buffer} data |
|
* @api private |
|
*/ |
|
|
|
Download.prototype.createFile = function (url, data) { |
|
return objectAssign(new Vinyl({ |
|
contents: data, |
|
path: filenamify(path.basename(url)) |
|
}), {url: url}); |
|
}; |
|
|
|
/** |
|
* Create stream |
|
* |
|
* @param {Object} file |
|
* @param {String} dest |
|
* @api private |
|
*/ |
|
|
|
Download.prototype.createStream = function (file, dest) { |
|
var stream = new PassThrough({objectMode: true}); |
|
var streams = [stream]; |
|
|
|
stream.end(file); |
|
|
|
if (this.opts.extract) { |
|
streams.push(decompress(this.opts)); |
|
} |
|
|
|
if (this.rename()) { |
|
streams.push(rename(this.rename())); |
|
} |
|
|
|
if (dest) { |
|
streams.push(vinylFs.dest(dest, this.opts)); |
|
} |
|
|
|
return streamCombiner.obj(streams); |
|
};
|
|
|