npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

downldr

v1.0.3

Published

A simple downloader that prevents writing invalid files

Downloads

3

Readme

Downldr

A simple downloader which prevents writing invalid files:

  • Will throw an error in case of non 2xx status code
  • Allows file type filtering

Install

npm install downldr

API

downldr(input, [options])

Returns a PassThrough stream with some extra events.

  • complete: When the target or returned stream is fully written.
  • type: Triggered when the file type is available & filter function is not passed or returned true.
  • abort: When the request is aborted.

input

Type: string / object (request options)

You can pass either an URL or an object that will be passed directly to request.

options (optional)

  • ignoreStatus - If true it will ignore non 2xx status code, defaults to false

  • target - Takes a function or a Writable Stream. When passed the response will be piped into this stream. If it's a function the file will be passed extension if available & must return a Writable Stream. The function will only be executed once the download is valid: 2xx status code & wasn't filtered by the filter function.

  • filter - which takes a function that should return false value if the download should be aborted.

This function will be triggered with the first chunk, and uses file-type to detect the file type.

function filter(type, chunk, statusCode) {
    // - type.mime may be null if `file-type` fails to detect the type
    // - type.contentType will always contain the response Conten-Type header
    // 		but the Content-Type header is not always 
    // 		accurate; A video with png extension
	return type.mime === 'image/jpeg'; // Only accepts jpeg
}

If the file type is not in this list type.mime will be undefined, but you can do the checks either using type.contentType or the first chunk

Note: type.mime may also be undefined for: docx/pptx/xlsx

The exception is detection of docx, pptx, and xlsx which potentially requires reading the whole file.

const downldr = require('downldr');

downldr('https://example.com/video.mp4')
	.on('error', console.error)
	.pipe(fs.createWriteStream('/tmp/video.mp4'))

downldr().abort()

This method will abort the current download. It uses request.abort()

const downldr = require('downldr');

const req = downldr('https://example.com/video.mp4')
	.on('error', console.error)
	.on('abort', () => console.log('Aborted!'));

req.abort();

.promise(input, options)

A convenient Promise wrapper around downldr.

options.target is required, since .pipe isn't available.

await downldr.promise('https://example.com/image', {
	filter: type => type && type.mime.startsWith('image/'),
	target: (ext) => fs.createWriteStream(`out.${ext}`)
});

Will resolve once target is fully written, and reject if an error occurs.

Examples

File type filter

const downldr = require('downldr');

downldr('https://example.com/image.jpg', {
	filter: (type, chunk, statusCode) => {
		// or check the first chunk or the statusCode
		return type.mime && type.mime.startsWith('image/');			
	}
})
.on('error', console.error)
.pipe(fs.createWriteStream('/tmp/image.jpg'))

Create stream on success

When saving the file to disk, a common practice is:

read
	.pipe(fs.createWriteStream('/tmp/file.txt');

But if the Readable stream fails, we end up with an empty file. To avoid that downldr can take a target option (function) which will be executed only when it's time to actually write to the stream.


downldr('https://example.com/image', {
	filter: type => type.mime == 'image/png',
	target: (ext) => fs.createWriteStream(`out.${ext}`)
})
.on('error', console.error)
.on('complete', () => console.log('done!'));

Set request Content-Type

const downldr = require('downldr');

app.get('/download/:image', (req, res) => {
	downldr(`http://example.com/${req.params.image}`, {
		filter: ({ mime = '' }) => {
		    // type.mime may be undefined for some files
		    // so we default it to = '' to safely use .startsWith
			return mime.startsWith('image/');			
		}
	})
	// 'type' is only triggered once filter returned true
	.on('type', type => res.set('Content-Type', type.mime))
	.on('error', err => {
		res.status(404)
			.send('Image not found')
	})
	.pipe(res); // Nothing will be piped if 'error' is triggered
});

License

ISC