Socket
Socket
Sign inDemoInstall

nodejs-file-downloader

Package Overview
Dependencies
10
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.10.6 to 4.11.0

fixtures/buba.jpeg

5

CHANGELOG.md

@@ -0,1 +1,6 @@

## 4.11.0 02/04/2023
### Added
- Added support for Data URI
## 4.10.6 07/01/2023

@@ -2,0 +7,0 @@

259

Download.js

@@ -10,13 +10,15 @@ const fs = require('fs');

const FileProcessor = require('./utils/FileProcessor');
const pipelinePromisified = util.promisify(stream.pipeline);
const mkdir = util.promisify(fs.mkdir);
const writeFile = util.promisify(fs.writeFile);
const { deduceFileName, exists } = require('./utils/fileName');
const { deduceFileName, exists, getTempFilePath } = require('./utils/fileName');
const { isJson } = require('./utils/string');
const { isDataUrl } = require('./utils/url');
const unlink = util.promisify(fs.unlink)
const rename = util.promisify(fs.rename)
const { bufferToReadableStream, createWriteStream, createBufferFromResponseStream, pipeStreams, getStringFromStream } = require('./utils/stream');
const downloadStatusEnum = {
COMPLETE:'COMPLETE',
ABORTED:"ABORTED"
COMPLETE: 'COMPLETE',
ABORTED: "ABORTED"
}

@@ -88,10 +90,8 @@

if (this.config.fileName && this.config.skipExistingFileName) {
if (await exists(this.config.directory + '/' + this.config.fileName)) {
return { downloadStatus: downloadStatusEnum.ABORTED, filePath: null }
}
if(await this._shouldSkipRequest()){
return { downloadStatus: downloadStatusEnum.ABORTED, filePath: null }
}
try {
const { dataStream, originalResponse } = await this._request();

@@ -101,9 +101,4 @@

if (originalResponse.statusCode > 226) {
await this._handlePossibleStatusCodeError({dataStream, originalResponse})
const error = await this._createErrorObject(dataStream, originalResponse)
throw error;
}
if (this.config.onResponse) {

@@ -117,5 +112,7 @@

let { finalFileName, originalFileName } = await this._getFileName(originalResponse.headers);
const finalPath = await this._save({ dataStream, originalResponse })
return { filePath:finalPath, downloadStatus: finalPath ? downloadStatusEnum.COMPLETE : downloadStatusEnum.ABORTED}
const finalPath = await this._getFinalPath({dataStream, finalFileName, originalFileName})
return { filePath: finalPath, downloadStatus: finalPath ? downloadStatusEnum.COMPLETE : downloadStatusEnum.ABORTED }
} catch (error) {

@@ -133,4 +130,29 @@

async _shouldSkipRequest() {
if (this.config.fileName && this.config.skipExistingFileName) {
if (await exists(this.config.directory + '/' + this.config.fileName)) {
return true
}
}
return false
}
/**
*
* @param {Object} obj
* @param {stream.Readable} obj.dataStream
* @param {http.IncomingMessage} obj.originalResponse
*/
async _handlePossibleStatusCodeError({dataStream, originalResponse}){
if (originalResponse.statusCode > 226) {
const error = await this._createErrorObject(dataStream, originalResponse)
throw error;
}
}
async _createErrorObject(dataStream, originalResponse) {
const responseString = await this._getStringFromStream(dataStream);
const responseString = await getStringFromStream(dataStream);

@@ -149,10 +171,4 @@ const error = new Error(`Request failed with status code ${originalResponse.statusCode}`)

async _getStringFromStream(stream) {
const buffer = await this._createBufferFromResponseStream(stream);
return buffer.toString();
}
/**

@@ -167,3 +183,2 @@ *

/**

@@ -173,41 +188,113 @@ * @return {Promise<{dataStream:stream.Readable,originalResponse:IncomingMessage}}

async _request() {
const { dataStream, originalResponse } = await this._makeRequest();
const headers = originalResponse.headers;
const contentLength = headers['content-length'] || headers['Content-Length'];
this.fileSize = parseInt(contentLength);
return { dataStream, originalResponse }
if (isDataUrl(this.config.url)) {
return this._mimic_RequestForDataUrl(this.config.url);
}
else {
const { dataStream, originalResponse } = await this._makeRequest();
const headers = originalResponse.headers;
const contentLength = headers['content-length'] || headers['Content-Length'];
this.fileSize = parseInt(contentLength);
return { dataStream, originalResponse };
}
}
/**
* @param {string} dataUrl
* @return {Promise<{dataStream:stream.Readable,originalResponse:IncomingMessage}}
*/
_mimic_RequestForDataUrl(dataUrl) {
const mimeType = dataUrl.match(/data:([^;]+);/)[1];
const base64Data = dataUrl.replace(/^data:[^;]+;base64,/, '');
const data = Buffer.from(base64Data, 'base64');
const dataStream = bufferToReadableStream(data);
const originalResponse = new IncomingMessage(null);
originalResponse.headers = {
'content-type': mimeType,
'content-length': data.byteLength
};
originalResponse.statusCode = 200;
this.fileSize = data.byteLength;
return { dataStream, originalResponse };
}
async _getFinalPath({ dataStream, finalFileName, originalFileName }) {
let finalPath
const shouldSkipSaving = await this._shouldSkipSaving(originalFileName)
if (!shouldSkipSaving) {
finalPath = await this._save({ dataStream, finalFileName, originalFileName });
} else {
finalPath = null
}
return finalPath
}
/**
* @param {Promise<{dataStream:stream.Readable,originalResponse:IncomingMessage}}
* @return {Promise<string | null>} finalPath
*
* @param {string} originalFileName
* @returns
*/
async _save({ dataStream, originalResponse }) {
async _shouldSkipSaving(originalFileName) {
if (this.config.skipExistingFileName && await exists(this.config.directory + '/' + originalFileName)) {
return true;
}
return false;
}
/**
*
* @param {string} finalFileName
* @returns {{finalPath:string,tempPath:string}}
*/
_getTempAndFinalPath(finalFileName) {
const finalPath = `${this.config.directory}/${finalFileName}`;
var tempPath = getTempFilePath(finalPath);
return { finalPath, tempPath }
}
async _saveAccordingToConfig({ dataStream, tempPath }) {
if (this.config.shouldBufferResponse) {
const buffer = await createBufferFromResponseStream(dataStream);
await this._saveFromBuffer(buffer, tempPath);
} else {
await this._saveFromReadableStream(dataStream, tempPath);
}
}
async _handleOnBeforeSave(finalFileName) {
if (this.config.onBeforeSave) {
const clientOverideName = await this.config.onBeforeSave(finalFileName)
if (clientOverideName && typeof clientOverideName === 'string') {
finalFileName = clientOverideName;
}
}
return finalFileName
}
/**
* @param {Promise<{dataStream:stream.Readable,finalFileName:string,originalFileName:string}}
* @return {Promise<string>} finalPath
*/
async _save({ dataStream, finalFileName, originalFileName }) {
try {
let { finalFileName, originalFileName } = await this._getFileName(originalResponse.headers);
if (this.config.skipExistingFileName && await exists(this.config.directory + '/' + originalFileName)) {
// will skip this request
if (await this._shouldSkipSaving(originalFileName)) {
return null;
}
if (this.config.onBeforeSave) {
const clientOverideName = await this.config.onBeforeSave(finalFileName)
if (clientOverideName && typeof clientOverideName === 'string') {
finalFileName = clientOverideName;
}
}
finalFileName = await this._handleOnBeforeSave(finalFileName)
const finalPath = `${this.config.directory}/${finalFileName}`;
const { finalPath, tempPath } = this._getTempAndFinalPath(finalFileName)
var tempPath = this._getTempFilePath(finalPath);
await this._saveAccordingToConfig({ dataStream, tempPath })
if (this.config.shouldBufferResponse) {
const buffer = await this._createBufferFromResponseStream(dataStream);
await this._saveFromBuffer(buffer, tempPath);
} else {
await this._saveFromReadableStream(dataStream, tempPath);
}
await this._renameTempFileToFinalName(tempPath, finalPath)

@@ -223,10 +310,5 @@

}
}
/**

@@ -254,31 +336,5 @@ *

return { dataStream, originalResponse }
}
}
/**
*
* @param {string} fullPath
* @return {Promie<WritableStream>}
*/
_createWriteStream(fullPath) {
return fs.createWriteStream(fullPath)
}
/**
*
* @param {stream.Readable} stream
* @returns
*/
async _createBufferFromResponseStream(stream) {
const chunks = []
for await (let chunk of stream) {
chunks.push(chunk)
}
const buffer = Buffer.concat(chunks)
return buffer;
}
_getProgressStream() {

@@ -313,18 +369,7 @@ const that = this;

}
async _pipeStreams(arrayOfStreams) {
await pipelinePromisified(...arrayOfStreams);
}
async _saveFromReadableStream(read, path) {
const streams = [read];
const write = this._createWriteStream(path)
const write = createWriteStream(path)
if (this.config.onProgress) {

@@ -336,9 +381,6 @@ const progressStream = this._getProgressStream()

streams.push(write)
await this._pipeStreams(streams)
await pipeStreams(streams)
}
async _saveFromBuffer(buffer, path) {

@@ -357,13 +399,4 @@ await writeFile(path, buffer)

/**
*
* @param {string} finalpath
*/
_getTempFilePath(finalpath) {
return `${finalpath}.download`;
}
/**
* @param {object} responseHeaders

@@ -398,7 +431,3 @@ */

}
}
}
}

@@ -72,3 +72,2 @@ const rpur = require('./utils/rpur')

// super();
if (!config || typeof config !== 'object') {

@@ -138,3 +137,2 @@ throw new Error('Must provide a valid config object')

debugger;

@@ -162,3 +160,2 @@ }

// console.log('e from shouldstop',e)
if (e.code === 'ERR_REQUEST_CANCELLED')//Means the request was cancelled, therefore no repetition is required.

@@ -165,0 +162,0 @@ return true;

@@ -15,2 +15,42 @@ const expect = require('expect')

it('Should download a picture from data URI', async () => {
const downloader = new Downloader({
url: `data:image/jpeg;base64,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`,
directory: "./downloads",
onProgress: (p, chunk) => {
expect(p).toBe('100.00')
},
onResponse: (r) => {
expect(r.constructor.name).toBe('IncomingMessage');
}
})
const { downloadStatus, filePath } = await downloader.download();
expect(downloadStatus).toBe('COMPLETE')
expect(filePath).toBe('./downloads/9k=.jpeg')
await verifyFile(filePath, 2339 );
})
it('Should download a picture from data URI, with custom name', async () => {
const downloader = new Downloader({
fileName:"buba.jpeg",
url: `data:image/jpeg;base64,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`,
directory: "./downloads",
onProgress: (p, chunk) => {
expect(p).toBe('100.00')
},
onResponse: (r) => {
expect(r.constructor.name).toBe('IncomingMessage');
},
onBeforeSave: (r) => {
return r.split(".")[0]+"2" + ".jpeg"
}
})
const { downloadStatus, filePath } = await downloader.download();
expect(downloadStatus).toBe('COMPLETE')
expect(filePath).toBe('./downloads/buba2.jpeg')
await verifyFile(filePath, 2339 );
})
it('Should download a picture and use content-type', async () => {

@@ -45,2 +85,4 @@ const host = randomHost()

it('Should get the deduced name', async () => {

@@ -47,0 +89,0 @@ let deducedName;

@@ -103,3 +103,2 @@ const { http, https } = require('follow-redirects');

const majorNodeVersion = process.versions.node.split('.')[0];
// debugger
if (!majorNodeVersion || majorNodeVersion < 14) {

@@ -106,0 +105,0 @@ request.abort()

{
"name": "nodejs-file-downloader",
"version": "4.10.6",
"version": "4.11.0",
"description": "A file downloader for NodeJs",

@@ -5,0 +5,0 @@ "main": "Downloader.js",

@@ -5,9 +5,5 @@ const sanitize = require('sanitize-filename');

const { promises: Fs } = require('fs')
const crypto = require('crypto');
/**

@@ -36,3 +32,2 @@ *

const fileNameFromContentDisposition = getFileNameFromContentDisposition(headers['content-disposition'] || headers['Content-Disposition']);
// console.log('filenamecontentdisposition', fileNameFromContentDisposition)
if (fileNameFromContentDisposition) return fileNameFromContentDisposition;

@@ -64,4 +59,3 @@

// var contentType = this.response.headers['content-type'] || this.response.headers['Content-Type'];
// console.log(contentType)
let extension = mime.extension(contentType)

@@ -109,2 +103,13 @@

module.exports = { deduceFileName, exists }
/**
*
* @param {string} finalpath
*/
function getTempFilePath(finalpath) {
return `${finalpath}.download`;
}
module.exports = { deduceFileName, exists,getTempFilePath }
const path = require('path');
const fs = require('fs');
// const { resolve } = require('path');
class FileProcessor {
constructor(config) {
this.originalFileName = config.fileName;

@@ -16,6 +14,6 @@ this.fileExtension = path.extname(this.originalFileName);

this.useSynchronousMode = config.useSynchronousMode || false;
}
getAvailableFileName() {

@@ -40,3 +38,3 @@ if (this.useSynchronousMode) {

pathExistsSync(path){
pathExistsSync(path) {
return fs.existsSync(path);

@@ -47,27 +45,7 @@ }

pathExists(path) {
// debugger;
if(this.useSynchronousMode){
// console.log('path',path)
if (this.useSynchronousMode) {
return this.pathExistsSync(path);
}
// console.log('useSynchronousMode',this.useSynchronousMode)
// return new Promise((resolve, reject) => {
// fs.open(path, 'r', (err) => {
// // debugger;
// if (err) {
// if (err.code === 'ENOENT') {
// // console.error('myfile does not exist');
// return resolve(false);
// }
// reject(err);
// }
// resolve(true);
// });
// })
return new Promise((resolve,reject)=>{
return new Promise((resolve, reject) => {
fs.access(path, (err) => {

@@ -81,4 +59,2 @@ if (err) {

})
}

@@ -90,3 +66,3 @@

if (!this.pathExistsSync(this.basePath +fileName)) {
if (!this.pathExistsSync(this.basePath + fileName)) {
return fileName;

@@ -96,3 +72,3 @@ }

counter = counter + 1;
let newFileName = this.fileNameWithoutExtension + "_"+ counter + this.fileExtension;
let newFileName = this.fileNameWithoutExtension + "_" + counter + this.fileExtension;

@@ -112,3 +88,3 @@ return this.createNewFileNameSync(newFileName, counter);

counter = counter + 1;
let newFileName = this.fileNameWithoutExtension + "_"+ counter + this.fileExtension;
let newFileName = this.fileNameWithoutExtension + "_" + counter + this.fileExtension;

@@ -120,35 +96,4 @@ return await this.createNewFileName(newFileName, counter);

// fileNameExistsSync(fileName) {
// if (this.useSynchronousMode) {
// return this.pathExists(this.basePath + fileName);
// }
// }
// fileNameExists(fileName) {
// return new Promise((resolve, reject) => {
// fs.open(this.basePath + fileName, 'r', (err) => {
// debugger;
// if (err) {
// if (err.code === 'ENOENT') {
// // console.error('myfile does not exist');
// return resolve(false);
// }
// reject(err);
// }
// resolve(true);
// });
// })
// }
}
module.exports = FileProcessor;

@@ -16,12 +16,6 @@ const {createDelay} = require('./delay')

*/
// async function repeatPromiseUntilResolved(...args) {//Destructuring arguments in order to avoid having the "attempts" counter as part of the API.
module.exports = async function rpur(promiseFactory,config={}) {
// const promiseFactory = args[0]
// const config = args[1]
// const attempts = args[2] || 0
// debugger;
const attempts = arguments[2] || 0
// console.log(attempts)
// const {maxRetries} = config
// debugger;
const dummy = () => false;

@@ -35,18 +29,11 @@ const shouldStop = config.shouldStop || dummy;

// console.log('Attempt number: ',attempts+1)
if (config.onAttempt) {
await config.onAttempt(attempts + 1)
}
// debugger;
const promise = promiseFactory();
const result = await promiseWithTimeout(promise, timeout);
// const result = await promiseFactory();
return result;
} catch (error) {
// debugger;
// console.log('Retrying failed promise');
// const newAttempts = attempts + 1;
if (config.onError) {
// debugger;
await config.onError(error, newAttempts)

@@ -58,7 +45,4 @@ }

throw error;
// console.log('Attempts', newAttempts)
// if (newAttempts == maxAttempts) {//If it reached the maximum allowed number of retries, it throws an error.
// throw error;
// }
if (delay) {

@@ -76,7 +60,5 @@ await createDelay(delay);

function promiseWithTimeout(promise, time) {
// debugger;
return new Promise(async (resolve, reject) => {
if (time) {
var timeout = setTimeout(() => {
// console.log('timed out!')
reject(new Error('Promise timed out as defined in the config'))

@@ -83,0 +65,0 @@ }, time)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc