@devteks/downloader
v0.0.4
Published
Simple node.js file downloader
Downloads
10
Readme
@devteks/downloader
Simple node.js file downloader
Features:
- Zero dependecies
- Pause / Resume
- Retry on fail
- Supports http / https
- Supports http redirects
- Supports pipes
- Custom native http request options
- Progress stats
Install
$ npm i @devteks/downloader
Usage
const { Downloader } = require('@devteks/downloader');
const downloader = new Downloader('https://proof.ovh.net/files/10Mb.dat', __dirname);
downloader.on('end', () => console.log('Download Completed'))
downloader.start();
CLI
This can be used as standalone CLI downloader
$ npm i -g @devteks/downloader
Usage: $ download [dir] url
dir
: destination folder to download the file to (optional).
url
: remote url to download.
$ download "./files" "https://proof.ovh.net/files/10Mb.dat"
Options
constructor(url, destination, options)
{
// Request body, can be any, string, object, etc.
body: null,
// Request Method Verb
method: 'GET',
// Custom HTTP Header ex: Authorization, User-Agent
headers: {},
// Custom filename when saved
fileName: string | cb(fileName, filePath, contentType)|{name, ext},
// { maxRetries: number, delay: number in ms } or false to disable (default)
retry: false,
// If the server does not return the "accept-ranges" header, can be force if it does support it
forceResume: false,
// remove the file when is stopped (default:true)
removeOnStop: true,
// remove the file when fail (default:true)
removeOnFail: true,
// interval time of the 'progress.throttled' event will be emitted
progressThrottle: 1000,
// Behavior when local file already exists
override: boolean | { skip, skipSmaller },
// Override the http request options
httpRequestOptions: {},
// Override the https request options, ex: to add SSL Certs
httpsRequestOptions: {},
}
for body
you can provide any parameter accepted by http.request write function req.write(body)
https://nodejs.org/api/http.html, when using this, you might need to add the content-length
and content-type
header in addition with the http method POST
or PUT
Example:
const data = JSON.stringify({ todo: 'Buy the milk' });
const dl = new Downloader('http://server/api/data.json', __dirname, {
method: 'POST',
body: data,
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
});
for fileName
you can provide 3 types of parameter
- string: will use the full string as the filename including extension
- callback(fileName, filePath, contentType): must return a string, only sync function are supported ex:
(fileName) => 'PREFIX_' + fileName;
, contentType will be provided if available - object: this object must contain a
name
attribute and an optionalext
attribute, theext
attribute can be an string without dot(.
) or a boolean wheretrue
use thename
as full file name (same as just giving a string to thefileName
parameter) or false (default) will only replace the name and keep the original extension, for example if the original name issomefile.dat
and the option is{name: 'newname'}
the output will besomename.dat
for override
you can provide 2 types of parameter
- boolean:
true
to override existing local file,false
to append '(number)' to new file name - object: object with properties
skip
(boolean): whether to skip download if file exists, andskipSmaller
(boolean): whether to skip download if file exists but is smaller. Both default tofalse
, for the equivalent ofoverride: true
.
for httpRequestOptions
the available options are detailed in here https://nodejs.org/api/http.html#http_http_request_options_callback
for httpsRequestOptions
the available options are detailed in here https://nodejs.org/api/https.html#https_https_request_options_callback
Methods
| Name | Description | |------|-------------| | start | Starts the downloading. | | pause | Pauses the downloading. | | resume | Resumes the downloading if supported, if not it will start from the beginning. | | stop | Stops the downloading and remove the file. | | pipe | Attaches a stream. | | unpipe | Detaches previously attached stream. | | unpipeAll | Detaches all piped streams. | | updateOptions | Updates the options, can be use on pause/resume events. | | getTotalSize | Gets the total file size from the server. |
Properties
| Name | Description | |-----------------|-------------------------------------------------------------------------------| | get requestUrl | Gets the request url. | | get stats | Gets stats from the current download, these are the same stats sent via progress event. | | get downloadPath | Gets the full path where the file will be downloaded, available after the start phase. | | get isResumable | Gets if the download can be resumable, available after the start phase. |
Events
| Name | Description |
|-------------------|------------------------------------------------------------------------------------|
| start | Emites when the start()
method is called. |
| skip | Emites when the download is skipped because the file already exists cb(skipInfo)
. |
| download | Emites when the download starts cb(downloadInfo)
. |
| progress | Emites every time gets data from the server cb(stats)
. |
| progressThrottled | The same as progress
but emits every 1 second while is downloading cb(stats)
. |
| retry | Emites when the download fails and retry is enabled cb(retryInfo)
. |
| end | Emites when the downloading has finished cb(downloadEndInfo)
. |
| error | Emites when there is any error cb(error)
. |
| timeout | Emites when the underlying socket times out from inactivity. |
| pause | Emites when the .pause method is called. |
| resume | Emites when the .resume method is called cb(isResume)
. |
| stop | Emites when the .stop method is called. |
| renamed | Emites when '(number)' is appended to the end of file, this requires override:false
opt, cb(renameInfo)
. |
| stateChanged | Emites when the state changes cd(state)
. |
event skip skipInfo
object
{
totalSize:, // total file size got from the server.
fileName:, // original file name
filePath:, // original path name
downloadedSize:, // the downloaded amount
}
event download downloadInfo
object
{
totalSize:, // total file size got from the server.
fileName:, // assigned name
filePath:, // download path
isResumed:, // if the download is a resume,
downloadedSize:, // the downloaded amount (only if is resumed otherwise always 0).
}
event progress or progressThrottled stats
object
{
name:, // file name
total:, // total size that needs to be downloaded in bytes.
downloaded:, // downloaded size in bytes
progress:, // progress porcentage 0-100%, (will be set as 0 if total is null)
speed: // download speed in bytes
}
event end downloadEndInfo
object
{
fileName:,
filePath:,
totalSize:, // total file size got from the server.
incomplete:, // true if the download endend but still incomplete
onDiskSize, // total size of file on the disk
downloadedSize:, // the total size downloaded
}
event renamed renameInfo
object
{
path:, // modified path name
fileName:, // modified file name
prevPath:, // original path name
prevFileName:, // original file name
}
event error error
object
{
message:, // Error message
status:, // Http status response if available
body:, // Http body response if available
}
States
| Name | Value | |---------------|-------| | IDLE | 'IDLE' | | SKIPPED | 'SKIPPED' | | STARTED | 'STARTED' | | DOWNLOADING | 'DOWNLOADING' | | PAUSED | 'PAUSED' | | RESUMED | 'RESUMED' | | STOPPED | 'STOPPED' | | FINISHED | 'FINISHED' | | FAILED | 'FAILED' | | RETRY | 'RETRY' |
Test
$ npm test
License
Read License for more licensing information.
Contributing
Read here for more information.
TODO
- Better code testing