HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux ip-172-31-4-197 6.8.0-1036-aws #38~22.04.1-Ubuntu SMP Fri Aug 22 15:44:33 UTC 2025 x86_64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/api-storage/node_modules/@xhmikosr/downloader/index.js
import events from 'node:events';
import fs from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
import contentDisposition from 'content-disposition';
import archiveType from '@xhmikosr/archive-type';
import decompress from '@xhmikosr/decompress';
import defaults from 'defaults';
import extName from 'ext-name';
import {fileTypeFromBuffer} from 'file-type';
import filenamify from 'filenamify';
import getStream from 'get-stream';
import got from 'got';

const defaultOptions = {
	got: {
		responseType: 'buffer',
		https: {
			rejectUnauthorized: process.env.npm_config_strict_ssl !== 'false',
		},
	},
	decompress: {},
};

const getExtFromMime = response => {
	const header = response.headers['content-type'];

	if (!header) {
		return null;
	}

	const exts = extName.mime(header);

	return exts.length === 1 ? exts[0].ext : null;
};

const getFilename = async (response, data) => {
	const header = response.headers['content-disposition'];

	if (header) {
		const parsed = contentDisposition.parse(header);

		if (parsed.parameters?.filename) {
			return parsed.parameters.filename;
		}
	}

	let filename = path.basename(new URL(response.requestUrl).pathname);

	if (!path.extname(filename)) {
		const fileType = await fileTypeFromBuffer(data);
		const ext = fileType?.ext || getExtFromMime(response);

		if (ext) {
			filename = `${filename}.${ext}`;
		}
	}

	return filename;
};

const filterEvents = async (name, listener) => {
	for await (const [message] of events.on(name, listener)) {
		if (message) {
			return message;
		}
	}
};

const download = (uri, output, options) => {
	if (typeof output === 'object') {
		options = output;
		output = null;
	}

	options = defaults(options, defaultOptions);

	const stream = got.stream(uri, options.got);

	const promise = filterEvents(stream, 'response')
		.then(response => {
			const encoding = options.got.responseType === 'buffer' ? 'buffer' : options.got.encoding;
			return Promise.all([getStream(stream, {encoding}), response]);
		})
		.then(async ([data, response]) => {
			const hasArchiveData = options.extract && await archiveType(data);

			if (!output) {
				return hasArchiveData ? decompress(data, options.decompress) : data;
			}

			const filename = options.filename || filenamify(await getFilename(response, data));
			const outputFilepath = path.join(output, filename);

			if (hasArchiveData) {
				return decompress(data, path.dirname(outputFilepath), options.decompress);
			}

			return fs
				.mkdir(path.dirname(outputFilepath), {recursive: true})
				.then(() => fs.writeFile(outputFilepath, data))
				.then(() => data);
		});

	// eslint-disable-next-line unicorn/no-thenable
	stream.then = promise.then.bind(promise);
	stream.catch = promise.catch.bind(promise);

	return stream;
};

export default download;