nodejs-file-downloader
Advanced tools
Comparing version 2.1.1 to 3.0.0
@@ -81,11 +81,11 @@ const fs = require('fs'); | ||
timeout: 6000, | ||
maxAttempts:1, | ||
maxAttempts: 1, | ||
useSynchronousMode: false, | ||
httpsAgent:undefined, | ||
headers:undefined, | ||
cloneFiles: true, | ||
httpsAgent: undefined, | ||
headers: undefined, | ||
cloneFiles: true, | ||
shouldBufferResponse: false, | ||
onResponse:undefined, | ||
onError:undefined, | ||
onProgress:undefined | ||
onResponse: undefined, | ||
onError: undefined, | ||
onProgress: undefined | ||
} | ||
@@ -98,4 +98,4 @@ | ||
if(this.config.filename){ | ||
this.config.fileName = this.config.filename | ||
if (this.config.filename) { | ||
this.config.fileName = this.config.filename | ||
} | ||
@@ -113,17 +113,36 @@ | ||
//For EventEmitter backwards compatibility | ||
on(event,callback){ | ||
on(event, callback) { | ||
this.config[`on${capitalize(event)}`] = callback | ||
} | ||
/** | ||
* @return {Promise<void>} | ||
*/ | ||
async download() { | ||
await this._makeUntilSuccessful(async () => { | ||
const response = await this._request(); | ||
// debugger; | ||
if (this.config.onResponse) { | ||
const shouldContinue = await this.config.onResponse(response); | ||
if(shouldContinue === false){ | ||
return; | ||
} | ||
} | ||
await this._save() | ||
}) | ||
} | ||
/** | ||
* @return {Promise<axios.AxiosResponse>} | ||
*/ | ||
async request() { | ||
// const response = await this._makeRequest(); | ||
async _request() { | ||
const response = await this._makeRequest(); | ||
// const response = await this._makeRequestUntilSuccessful(); | ||
const response = await this._makeUntilSuccessful(this._makeRequest); | ||
// const response = await this._makeUntilSuccessful(this._makeRequest); | ||
this.response = response; | ||
if (this.config.onResponse) { | ||
await this.config.onResponse(response); | ||
} | ||
const contentLength = response.headers['content-length'] || response.headers['Content-Length']; | ||
@@ -138,3 +157,3 @@ this.fileSize = parseInt(contentLength); | ||
*/ | ||
async save() { | ||
async _save() { | ||
if (this.config.shouldBufferResponse) { | ||
@@ -151,14 +170,4 @@ // debugger; | ||
/** | ||
* @return {Promise<void>} | ||
*/ | ||
async download() { | ||
await this.request(); | ||
// debugger; | ||
await this.save() | ||
} | ||
/** | ||
@@ -179,3 +188,3 @@ * @param {Function} asyncFunc | ||
}, { | ||
onError: async(e) => { | ||
onError: async (e) => { | ||
// debugger; | ||
@@ -186,3 +195,3 @@ if (this.config.onError) { | ||
}, | ||
maxAttempts:this.config.maxAttempts | ||
maxAttempts: this.config.maxAttempts | ||
// maxAttempts:1 | ||
@@ -251,2 +260,3 @@ }) | ||
// yoyo | ||
// debugger; | ||
const fileName = await this._getFinalFileName(); | ||
@@ -256,4 +266,5 @@ | ||
const write = this._createWriteStream(`${this.config.directory}/${fileName}`) | ||
// debugger | ||
await pipeline(read, progress, write) | ||
// debugger; | ||
@@ -260,0 +271,0 @@ } |
@@ -10,5 +10,7 @@ | ||
const Downloader = require('./Downloader'); | ||
const { Readable } = require('stream'); | ||
describe('Downloader tests', () => { | ||
@@ -71,3 +73,3 @@ | ||
cloneFiles: false, | ||
onProgress:(p, chunk) => { | ||
onProgress: (p, chunk) => { | ||
// console.log(p, chunk) | ||
@@ -78,3 +80,3 @@ expect(!isNaN(parseFloat(p)) && isFinite(p)).toBe(true) | ||
}, | ||
onResponse:(r) => { | ||
onResponse: (r) => { | ||
// console.log(Object.getPrototypeOf(r).constructor.name) | ||
@@ -86,13 +88,13 @@ expect(r).toHaveProperty('data'); | ||
}) | ||
// .on('progress', (p, chunk) => { | ||
// // console.log(p, chunk) | ||
// expect(!isNaN(parseFloat(p)) && isFinite(p)).toBe(true) | ||
// expect(Object.getPrototypeOf(chunk).constructor.name).toBe('Buffer') | ||
// .on('progress', (p, chunk) => { | ||
// // console.log(p, chunk) | ||
// expect(!isNaN(parseFloat(p)) && isFinite(p)).toBe(true) | ||
// expect(Object.getPrototypeOf(chunk).constructor.name).toBe('Buffer') | ||
// }) | ||
// .on('response', (r) => { | ||
// // console.log(Object.getPrototypeOf(r).constructor.name) | ||
// expect(r).toHaveProperty('data'); | ||
// expect(r).toHaveProperty('headers'); | ||
// }) | ||
// }) | ||
// .on('response', (r) => { | ||
// // console.log(Object.getPrototypeOf(r).constructor.name) | ||
// expect(r).toHaveProperty('data'); | ||
// expect(r).toHaveProperty('headers'); | ||
// }) | ||
// console.log(downloader) | ||
@@ -105,3 +107,3 @@ // debugger; | ||
}) | ||
@@ -132,3 +134,3 @@ | ||
}) | ||
@@ -158,3 +160,3 @@ | ||
}) | ||
@@ -185,3 +187,3 @@ | ||
}) | ||
@@ -213,3 +215,3 @@ | ||
}) | ||
@@ -240,3 +242,3 @@ | ||
}) | ||
@@ -268,3 +270,3 @@ | ||
}) | ||
@@ -296,3 +298,3 @@ | ||
}) | ||
@@ -336,3 +338,3 @@ | ||
} catch (error) { | ||
@@ -376,8 +378,8 @@ console.log(error) | ||
} catch (error) { | ||
// debugger; | ||
}finally{ | ||
await verifyFile('./downloads/Koala.jpg', 29051); | ||
} finally { | ||
await verifyFile('./downloads/Koala.jpg', 29051); | ||
} | ||
@@ -400,3 +402,3 @@ | ||
directory: "./downloads", | ||
maxAttempts:3 | ||
maxAttempts: 3 | ||
}) | ||
@@ -439,3 +441,3 @@ // console.log(downloader) | ||
stream, | ||
{'Content-Type': 'image/jpeg'} | ||
{ 'Content-Type': 'image/jpeg' } | ||
]; | ||
@@ -451,5 +453,5 @@ }); | ||
directory: "./downloads", | ||
maxAttempts:3, | ||
onError:(e) => { | ||
debugger; | ||
maxAttempts: 3, | ||
onError: (e) => { | ||
// debugger; | ||
onErrorCount++; | ||
@@ -468,16 +470,17 @@ // console.log(e.message) | ||
// }) | ||
// await downloader.download(); | ||
const request = await downloader.request() | ||
await downloader.save() | ||
await downloader.download(); | ||
// const request = await downloader.request() | ||
// debugger; | ||
var s = request.data; | ||
// await downloader.save() | ||
// debugger; | ||
// var s = request.data; | ||
// debugger; | ||
} catch (error) { | ||
// debugger; | ||
}finally{ | ||
// debugger; | ||
expect(s.constructor.name).toBe('ReadStream') | ||
debugger; | ||
} finally { | ||
debugger; | ||
// expect(s.constructor.name).toBe('ReadStream') | ||
expect(onErrorCount).toBe(2) | ||
@@ -493,5 +496,5 @@ await verifyFile('./downloads/400.jpeg', 29051); | ||
it('Should fail once and finally fail', async () => { | ||
mock.onGet("/500").reply(500); | ||
@@ -504,3 +507,3 @@ var onErrorCount = 0; | ||
directory: "./downloads", | ||
maxAttempts:1, | ||
maxAttempts: 1, | ||
onError: (e) => { | ||
@@ -524,3 +527,3 @@ // debugger; | ||
// debugger; | ||
}finally{ | ||
} finally { | ||
// debugger; | ||
@@ -536,52 +539,175 @@ // expect(s.constructor.name).toBe('ReadStream') | ||
// it('Should fail three times during stream', async function() { | ||
// // this.timeout(10000) | ||
it('Should fail three times during stream, and then succeed', async function () { | ||
// this.timeout(10000) | ||
let counter = 0 | ||
const stream = fs.createReadStream(Path.join(__dirname, 'fixtures/Koala.jpg')); | ||
mock.onGet("/koala.jpg").reply(function (config) { | ||
// const { Readable } = require('stream'); | ||
const modifiedStream = Readable.from((async function* () { | ||
counter++ | ||
if (counter === 4) { | ||
for await (const chunk of stream) { | ||
yield chunk; | ||
} | ||
} else { | ||
throw new Error('LOL'); | ||
} | ||
})()); | ||
return [ | ||
200, | ||
modifiedStream, | ||
{} | ||
]; | ||
}); | ||
try { | ||
let error; | ||
const downloader = new Downloader({ | ||
timeout: 1000, | ||
// debugMode:true, | ||
maxAttempts: 4, | ||
// onResponse:function(r){ | ||
// if(r.headers=== 'yoyo'){ | ||
// error='yoyo' | ||
// return false | ||
// } | ||
// }, | ||
url: '/koala.jpg', | ||
directory: "./downloads", | ||
}) | ||
var onErrorCount = 0 | ||
downloader.on('error', (e) => { | ||
// debugger; | ||
onErrorCount++; | ||
}) | ||
// const response = await downloader.request() | ||
// debugger; | ||
// await downloader.save() | ||
// debugger; | ||
await downloader.download(); | ||
} catch (error) { | ||
debugger; | ||
// console.log(error) | ||
} finally { | ||
debugger; | ||
expect(onErrorCount).toBe(3) | ||
// await verifyFile('./downloads/koala.jpg', 29051); | ||
} | ||
}) | ||
it('Should use onResponse to stop download', async function () { | ||
// mock.onGet("/fileThatDoesntExist").reply(function (config) { | ||
// // debugger; | ||
// const stream = fs.createReadStream(Path.join(__dirname, 'fixtures/Desert.jpg')); | ||
// stream.destroy(); | ||
// return [ | ||
// 200, | ||
// stream, | ||
// {} | ||
// ]; | ||
// }); | ||
const stream = fs.createReadStream(Path.join(__dirname, 'fixtures/Koala.jpg')); | ||
mock.onGet("/koala.jpg").reply(function (config) { | ||
return [ | ||
200, | ||
stream, | ||
{'message':'terminate'} | ||
]; | ||
}); | ||
// try { | ||
// const downloader = new Downloader({ | ||
// timeout: 1000, | ||
// url: '/fileThatDoesntExist', | ||
// directory: "./downloads", | ||
// }) | ||
const downloader = new Downloader({ | ||
timeout: 1000, | ||
// debugMode:true, | ||
maxAttempts: 4, | ||
fileName:'yoyo', | ||
onResponse: function (response) { | ||
if (response.headers['message'] !== 'terminate') { | ||
// return true | ||
} | ||
return false; | ||
}, | ||
url: '/koala.jpg', | ||
directory: "./downloads", | ||
// var onErrorCount = 0 | ||
// downloader.on('error', (e) => { | ||
// onErrorCount++; | ||
// }) | ||
// const request = await downloader.request() | ||
// debugger; | ||
// await downloader.save() | ||
// debugger; | ||
// // await downloader.download(); | ||
// } catch (error) { | ||
// debugger; | ||
// // console.log(error) | ||
// }finally{ | ||
// debugger; | ||
// expect(onErrorCount).toBe(3) | ||
// } | ||
}) | ||
try { | ||
await downloader.download(); | ||
debugger; | ||
} catch (error) { | ||
debugger; | ||
throw error | ||
} | ||
try { | ||
await verifyFile('./downloads/yoyo', 29051); | ||
} catch (error) { | ||
debugger | ||
return; | ||
} | ||
throw new Error(); | ||
// }) | ||
}) | ||
it('Should use onResponse to continue download', async function () { | ||
const stream = fs.createReadStream(Path.join(__dirname, 'fixtures/Koala.jpg')); | ||
mock.onGet("/koala.jpg").reply(function (config) { | ||
return [ | ||
200, | ||
stream, | ||
{'message':'do not terminate'} | ||
]; | ||
}); | ||
const downloader = new Downloader({ | ||
timeout: 1000, | ||
// debugMode:true, | ||
maxAttempts: 4, | ||
onResponse: function (response) { | ||
if (response.headers['message'] !== 'terminate') { | ||
// return true | ||
return; | ||
} | ||
return false; | ||
}, | ||
url: '/koala.jpg', | ||
directory: "./downloads", | ||
}) | ||
const prom = await downloader.download(); | ||
debugger; | ||
// try { | ||
await verifyFile('./downloads/koala.jpg', 29051); | ||
// } catch (error) { | ||
// debugger | ||
// return; | ||
// } | ||
// throw new Error(); | ||
}) | ||
}) | ||
{ | ||
"name": "nodejs-file-downloader", | ||
"version": "2.1.1", | ||
"version": "3.0.0", | ||
"description": "A file downloader for NodeJs", | ||
@@ -5,0 +5,0 @@ "main": "Downloader.js", |
@@ -1,2 +0,2 @@ | ||
nodejs-file-downloader is a simple utility for downloading files. It hides the complexity of dealing with streams, paths and duplicate file names. Can automatically repeat failed requests. | ||
nodejs-file-downloader is a simple utility for downloading files. It hides the complexity of dealing with streams, paths and duplicate file names. Can automatically repeat failed downloads. | ||
@@ -16,4 +16,4 @@ If you encounter any bugs or have a question, please don't hesitate to open an issue. | ||
* [Overwrite existing files](#overwrite-existing-files) | ||
* [Get response and then download](#get-response-and-then-download) | ||
* [Repeat failed requests automatically](#repeat-failed-requests-automatically) | ||
* [Hook into response](#hook-into-response) | ||
* [Repeat failed downloads automatically](#repeat-failed-downloads-automatically) | ||
@@ -100,25 +100,27 @@ ## Examples | ||
#### Get response and then download | ||
#### Hook into response | ||
There is an alternative way to using Downloader.download(): | ||
If you need to get the underlying response, in order to decide whether the download should continue, or perform any other operations, use the onReponse hook. | ||
```javascript | ||
//The response object is an Axios response object. Refer to their docs for more details. | ||
function onResponse(response){ | ||
//Now you can do something with the response, like check the headers | ||
if(response.headers['content-length'] > 1000000){ | ||
console.log('File is too big!') | ||
return false;//If you return false, the download process is stopped, and downloader.download() is resolved. | ||
} | ||
//Returning any other value, including undefined, will tell the downloader to proceed as usual. | ||
} | ||
const downloader = new Downloader({ | ||
url: 'http://212.183.159.230/200MB.zip', | ||
directory: "./", | ||
directory: "./", | ||
onResponse | ||
}) | ||
const response = await downloader.request()//This function just performs the request. The file isn't actually being downloaded yet. It returns an Axios response object. You can refer to their docs for more details. | ||
const response = await downloader.download() | ||
//Now you can do something with the response, like check the headers | ||
if(response.headers['content-length'] < 1000000){ | ||
await downloader.save() | ||
}else{ | ||
console.log('File is too big!') | ||
} | ||
//Note that Downloader.download() simply combines these two function calls. | ||
``` | ||
@@ -130,7 +132,6 @@ | ||
#### Repeat failed requests automatically | ||
#### Repeat failed downloads automatically | ||
The program can repeat any failed http request automatically. Only if the provided config.maxAttempts number is exceeded, an Error is thrown. | ||
The program can repeat any failed downloads automatically. Only if the provided config.maxAttempts number is exceeded, an Error is thrown. | ||
Note that currently only the http requests will be repeated in case of an error, BUT NOT THE STREAM ITSELF. If a stream fails on its first attempt, an error is thrown as usual. I will change this behavior in the future. | ||
@@ -143,3 +144,3 @@ ```javascript | ||
maxAttempts:3,//Default is 1. | ||
onError:function(error){//You can also hook into each failed http request attempt. | ||
onError:function(error){//You can also hook into each failed attempt. | ||
console.log('Error from attempt ',error) | ||
@@ -146,0 +147,0 @@ } |
@@ -9,2 +9,3 @@ const sanitize = require('sanitize-filename'); | ||
/** | ||
@@ -11,0 +12,0 @@ * |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
142745
1033
152