Browse Source

Refactor File class to include download progress and error handling

node16
Onja 12 months ago
parent
commit
d1052f693a
  1. 47
      src/models/File.js

47
src/models/File.js

@ -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;
Loading…
Cancel
Save