|
|
@ -7,7 +7,6 @@ const https = require('https'); |
|
|
|
const exec = util.promisify(require('child_process').exec); |
|
|
|
|
|
|
|
const EventEmitter = require('events'); |
|
|
|
const csv = require('csv-parser'); |
|
|
|
const slugify = require('slugify'); |
|
|
|
|
|
|
|
const dest = path.join(appRoot, 'public/csv'); |
|
|
@ -22,7 +21,10 @@ function generateFilePath(filename) { |
|
|
|
// Create a class File that extends EventEmitter
|
|
|
|
class File extends EventEmitter { |
|
|
|
|
|
|
|
// Create a constructor that takes a url as a parameter
|
|
|
|
/** |
|
|
|
* Create a new File instance |
|
|
|
* @param {string} url |
|
|
|
*/ |
|
|
|
constructor(url) { |
|
|
|
super(); |
|
|
|
this.url = url; |
|
|
@ -30,7 +32,10 @@ class File extends EventEmitter { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create a download method that downloads the file from the url
|
|
|
|
/** |
|
|
|
* Download a file from a url |
|
|
|
* @returns {Promise<string>} filepath |
|
|
|
*/ |
|
|
|
async download() { |
|
|
|
const url = URL.parse(this.url); |
|
|
|
this.filename = slugify(url.hostname, { lower: true }); |
|
|
@ -46,13 +51,41 @@ class File extends EventEmitter { |
|
|
|
file.on('error', (err) => { |
|
|
|
fs.unlink(filepath, () => { |
|
|
|
// Emit a download.error event with the error
|
|
|
|
this.emit('download.error', { url: this.url, filepath: this.filepath, error: err, type: 'file' }); |
|
|
|
this.emit('download.error', { url: this.url, filepath: this.filepath, error: err.message, type: 'file' }); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
request |
|
|
|
.get(url.href, (response) => { |
|
|
|
// Check if response is valid
|
|
|
|
if (response.statusCode !== 200) { |
|
|
|
// Emit a download.error event with the error
|
|
|
|
this.emit('download.error', { url: this.url, filepath: this.filepath, error: response.statusMessage, type: 'response' }); |
|
|
|
return reject(response.statusMessage); |
|
|
|
} |
|
|
|
|
|
|
|
// Get the content length and parse it to an integer
|
|
|
|
const contentLength = parseInt(response.headers['content-length'], 10); |
|
|
|
|
|
|
|
const step = Math.floor(contentLength / 100); |
|
|
|
let stepLimit = step; |
|
|
|
// Create a variable to hold the downloaded size
|
|
|
|
let downloaded = 0; |
|
|
|
|
|
|
|
// Handle response data
|
|
|
|
response.on('data', (chunk) => { |
|
|
|
// Add the size of the chunk to the downloaded variable
|
|
|
|
downloaded += chunk.length; |
|
|
|
|
|
|
|
// Check if the downloaded size is bigger than the step limit
|
|
|
|
if (downloaded > stepLimit) { |
|
|
|
// Emit a download.progress event with the url, filepath and downloaded size
|
|
|
|
this.emit('download.progress', { url: this.url, filepath: this.filepath, percentage: Math.floor((downloaded / contentLength) * 100) }); |
|
|
|
stepLimit += step; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
response.pipe(file); |
|
|
|
|
|
|
|
file.on('finish', () => { |
|
|
@ -66,10 +99,12 @@ class File extends EventEmitter { |
|
|
|
.on('error', (err) => { |
|
|
|
fs.unlink(filepath, () => { |
|
|
|
// Emit a download.error event with the error
|
|
|
|
this.emit('download.error', { url: this.url, filepath: this.filepath, error: err, type: 'request' }); |
|
|
|
this.emit('download.error', { url: this.url, filepath: this.filepath, error: err.message, type: 'request' }); |
|
|
|
reject(err.message); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
module.exports = File; |