Giter VIP home page Giter VIP logo

probe-image-size's Introduction

probe-image-size

CI NPM version Coverage Status

Get image size without full download. Supported image types: JPG, GIF, PNG, WebP, BMP, TIFF, SVG, PSD, ICO, AVIF, HEIC, HEIF.

Key features:

  • small size, no heavy dependencies
  • works with remote and local data
  • effective with big images (speed/memory), download minimal data from remotes
  • extracts orientation value when available
  • easy to browserify (splitted to components)

Install

npm install probe-image-size

Example

const probe = require('probe-image-size');

// Get by URL
let result = await probe('http://example.com/image.jpg');
console.log(result); // =>
/*
  {
    width: xx,
    height: yy,
    type: 'jpg',
    mime: 'image/jpeg',
    wUnits: 'px',
    hUnits: 'px',
    url: 'http://example.com/image.jpg'
  }
*/


// By URL with options
let result = await probe('http://example.com/image.jpg', { rejectUnauthorized: false });
console.log(result);


// From the stream
let result = await probe(require('fs').createReadStream('image.jpg'));
console.log(result);


// From a Buffer (sync)
let data = require('fs').readFileSync('image.jpg');
console.log(probe.sync(data));

API

Note:

  • You can access/browserify stream.js / http.js / sync.js directly.
  • If you don't like http.js dependencies, you can create your own wrapper for stream.js.

probe(src [, options|keepOpen]) -> Promise

  • src can be of this types:
    • String - URL to fetch
    • Stream - readable stream
  • options - HTTP only. See needle documentation, and customized defaults.
  • keepOpen (Boolean) - stream only. Keep stream open after parser finishes (input stream will be closed by default)

result (Promise) contains:

{
  width: XX,
  height: YY,
  length: ZZ,   // byte length of the file (if available, HTTP only)
  type: ...,    // image 'type' (usual file name extention)
  mime: ...,    // mime type
  wUnits: 'px', // width units type ('px' by default, can be different for SVG)
  hUnits: 'px', // height units type ('px' by default, can be different for SVG)
  url: ...,     // HTTP only, last url for the image in chain of redirects
                // (if no redirects, same as src)

  // optional, image orientation (from Exif), number from 1 to 8;
  // you may wish to swap width and height if orientation is >= 5
  orientation: X,

  // optional, full list of sizes for ICO (always) and AVIF (if multiple images)
  variants: [ { width, height }, ... ] | undefined
}

Width and height in the output object represent image size before any transformations (orientation, cropping) are applied. Orientation is returned separately, which you may wish to apply afterwards depending on browser support (browsers only support JPEG orientation for now). See known issues for details.

Returned errors can be extended with 2 fields:

  • code - equals to ECONTENT if the library failed to parse the file;
  • status - equals to a HTTP status code if it receives a non-200 response.

probe.sync(src) -> result|null

Sync version can eat arrays, typed arrays and buffers. On success it returns the same result as async version. On fail it returns null.

Note. Formats like JPEG & TIFF can store size anywhere (far from the head). That usually does not happens, but if you need guarantees - always provide full file content to sync methods. We strongly recommend to use async version as memory-friendly.

Similar projects

Support probe-image-size

You can support this project via Tidelift subscription.

probe-image-size's People

Contributors

boromisp avatar crux153 avatar e2e8 avatar leolabs avatar mberneti avatar misos1 avatar rlidwka avatar vanderhoorn avatar winglian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

probe-image-size's Issues

TypeError: NetworkError when attempting to fetch resource.

hi,here is my code.
probe('https://obs-xy-test.obs.cn-east-2.myhuaweicloud.com/5807ad7a07bc4a26a1f4b22d4a33f218.jpeg') .then((res) => { console.log(res); }) .catch((err) => { console.log(err); });

error:TypeError: NetworkError when attempting to fetch resource.
browser:FireFox 84.0.1

API / streams cleanup

  • Use pump to close input stream, end-of-stream and so on.
  • Terminate early. Don't wait all parcers if one returned positive result.
  • Try to detach finished decoder stream instead of skip

EPIPE or freeze when using probe in http server with keepalive

let http = require("http");
let probe = require("probe-image-size");

let server = http.createServer(async function(req, res)
{
	res.end(JSON.stringify(await probe(req)));
});

(async function()
{
	await new Promise(resolve => server.listen(8888, resolve));
	let agent = new http.Agent({ keepAlive: true });
	let svg = `<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100pt" height="100pt" viewBox="0 0 100 100" version="1.1">`;
	for(let i = 0; i < 100000; i++) svg += " ";
	for(let i = 0; ; i++)
	{
		console.log(i);
		let req = http.request({ port: 8888, method: "post", agent }).end(svg);
		let res = await new Promise((resolve, reject) => req.on("response", resolve).on("error", reject));
		let str = "";
		for await (let chunk of res) str += chunk;
		console.log(str);
	}
}());

Possible output (when is req closed by probe then is sometimes not possible to send response):

0
{"width":100,"height":100,"type":"svg","mime":"image/svg+xml","wUnits":"pt","hUnits":"pt"}
1
node:internal/process/promises:245
          triggerUncaughtException(err, true /* fromPromise */);
          ^

Error: write EPIPE
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writevGeneric (node:internal/stream_base_commons:143:3)
    at Socket._writeGeneric (node:net:771:11)
    at Socket._writev (node:net:780:8)
    at doWrite (node:internal/streams/writable:412:12)
    at clearBuffer (node:internal/streams/writable:565:5)
    at Socket.Writable.uncork (node:internal/streams/writable:354:7)
    at ClientRequest._flushOutput (node:_http_outgoing:949:10)
    at ClientRequest._flush (node:_http_outgoing:918:22)
    at onSocketNT (node:_http_client:835:9) {
  errno: -32,
  code: 'EPIPE',
  syscall: 'write'
}

When is server part changed to this then it freezes after some time (sending response does not dump partially read request anymore nodejs/node@3d480dc):

let server = http.createServer(async function(req, res)
{
	res.end(JSON.stringify(await probe(req, true)));
});

So neither true or false keepOpen does help here. Maybe would be good to have another option which will cause that source stream will be read (and ignored) to end after is probe successful. Or maybe it should do this whether it is successful or encountered error so also in case of error can be send meaningful error response to client.

Maybe keepOpen set to true should actually mean (and be renamed to something else like dontClose or dontDestroy) that stream is not closed but read to end (dumped). Because stream which is not read to end or closed is really bad situation, for file stream this means leak, for http stream leak and possibly other problems as mentioned above. What is user supposed to do with partially read stream anyway? (Ok one possible use case is when is stream piped to multiple destinations, but I think there should be also option to read it to end by probe itself which covers also this situation anyway.)

video support

I love how smart is this library, congratulations ❤️

Do you think that could be used the same approach for detecting the same properties but for videos?

Not sure how much technically different they are from images

How many bytes are needed to make a determination?

Based on my testing, it seems the number of bytes needed to retrieve the metadata about the image varies. Is there some some maximum or is there no cap on the number of bytes needed before we are able to make a determination on image size?

I'm in a situation where I'd like to retrieve the metadata using probe-image-size from a stream and then continue (without creating a brand new stream) streaming the data into some transformations. In order to do this, I think the best way would be to use a PassThrough to buffer the data needed by probe-image-size before sending off to the transformations. So it looks something like this:

const readPassThrough = new PassThrough();
const readProxy = pipeline(readStream, readPassThrough, ()=> {});
const fileMetadata = await probe(readStream);
readProxy.pipe(transformer).pipe(writeStream);

The problem I ran into is that probe-image-size fetched about 50815 bytes for a JPEG I tested with before being able to output the image metadata. This is bigger than the default highWaterMark for the PassThrough, which is 16384 bytes. So the PassThrough couldn't accept the 50815 bytes, causing backpressure, which stopped the entire pipeline. So, in order to make this example work, I'd have to use const readPassThrough = new PassThrough({ highWaterMark: 51200 });. I'm wondering if there is some max value I can set highWaterMark to in order to guarantee I wouldn't run into backpressure issues. If not, I may have to just create a new read stream after probing the metadata and accept the performance hit.

Thanks in advance for the help!

Add response headers to response

The way I implemented it was like this (in stream.js):

function resolve1(data) {
  data.headers = stream.headers;
  resolve(data);
}
...
pStream.once('data', resolve1);

This is very useful for my use case, where I need to know various other headers as well as just the size.

Add SVG support

  • Need streaming parser
    • need quick fail (if data does not starts with <)
    • avoid binary to text conversion before quick fail phase
    • may be sax could help (after quick fail passed)
  • Design API to be compatible - SVG can have floating & not numeric size
  • Should we allow to disable SVG mode?

async probe hangs with json file

Hello 👋,

I'm a happy user of this library but just observed something very unexpected:

calling probe(url) with e.g. this url containing a json will result in a never-resolving promise.

It seems to be the case that it hangs for any kind of json file. (even a file containing only {})

I've updated to 7.2.0 and could still observe this behaviour.

Promise.prototype.then() not to spec

Following the spec Promise.prototype.then should contain a second optional parameter onRejected so one doesn't need to add a chained catch() but with probe-image-size it does not.

So, instead of being able to do this:

probe(fileStream).then(dims => {
   ...
}, err => {
   ...
});

we are forced to do this:

probe(fileStream).then(dims => {
   ...
}).catch( err => {
   ...
});

A text/html be recognized as an image

var probe = require('probe-image-size')
probe("https://nodejs.org/dist/latest-v14.x/docs/api/stream.html").then(console.log)

output:

{
  width: 24,
  height: 24,
  type: 'svg',
  mime: 'image/svg+xml',
  wUnits: 'px',
  hUnits: 'px',
  url: 'https://nodejs.org/dist/latest-v14.x/docs/api/stream.html'
}

Dev memo

Here is the place to collect things, that nobody plan to implement. If you need those - PR welcome.

  • dds support (with arrays)
  • jxr support (#10)
  • data-uri support (but not sure)

Unrecognized file format error in 4.0.0

Issue

Context

  • Using 4.0.0 (I got the error)
  • Using 3.2.0 (I don't get the error)

Logs

error: controllers/utils-api-controller image-size.error Error while getting url: https://prod.media.larepublica.pe/1200x630/larepublica/imagen/2018/04/28/noticia-34-4-cm-estadio-elias-aguirre_watermark.jpg message=unrecognized file format, stack=ProbeError: unrecognized file format
    at ParserStream.parserEnd (/Users/yhon/development/env-9000/limber-public/node_modules/probe-image-size/stream.js:29:24)
    at Object.onceWrapper (events.js:277:13)
    at ParserStream.emit (events.js:189:13)
    at endReadableNT (_stream_readable.js:1125:12)
    at process._tickCallback (internal/process/next_tick.js:63:19), name=ProbeError, code=ECONTENT
    1) https://prod.media.larepublica.pe/1200x630/larepublica/imagen/2018/04/28/noticia-34-4-cm-estadio-elias-aguirre_watermark.jpg returns body different than null

Add a sync version?

For writing shell scripts in Node.js, I like the sync versions of tool functions. Maybe add one for probe-image-size?

it will last forever if probe a link to a pdf file

We accidently found a problem when our users choose a pdf file and the logic using probe running forever with this file. it is of course that we should validate but it is a case that can cause forever running. I think we might need timeout to handle this case also.

"x-exr" type image not work

I got an error as below, when put xxx.exr image.

ProbeError: unrecognized file format
    at ParserStream.parserEnd (/Users/user/Workspace/app/node_modules/probe-image-size/stream.js:39:28)
    at Object.onceWrapper (events.js:421:28)
    at ParserStream.emit (events.js:315:20)
    at endReadableNT (_stream_readable.js:1221:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) {
  code: 'ECONTENT'
}

Gotcha: probe-image-size does not work with gzip encoded streams

If a gzip encoded stream is requested via the accept-encoding header, probe-image-size fails with unrecognized file format:

const probe = require("probe-image-size");
probe(
  "https://www.washingtonpost.com/graphics/2018/lifestyle/magazine/amp-stories/tangent-big-change-means-big-risk/img/Tangent_Rebrand_1.jpg",
  { headers: { "accept-encoding": "gzip" }
  }).then(console.log, console.error);

Actual result:

{ ProbeError: unrecognized file format
    at ParserStream.parserEnd (/Users/stillers/workspace/ampbench/amp-story/linter/node_modules/probe-image-size/stream.js:29:24)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:111:20)
    at ParserStream.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1064:12)
    at _combinedTickCallback (internal/process/next_tick.js:139:11)
    at process._tickCallback (internal/process/next_tick.js:181:9)
  name: 'ProbeError',
  message: 'unrecognized file format',
  code: 'ECONTENT' }

Expected result (without accept-encoding: gzip):

{ width: 1162,
  height: 2066,
  type: 'jpg',
  mime: 'image/jpeg',
  wUnits: 'px',
  hUnits: 'px',
  url: 'https://www.washingtonpost.com/graphics/2018/lifestyle/magazine/amp-stories/tangent-big-change-means-big-risk/img/Tangent_Rebrand_1.jpg' }

I suppose this is more or less working as intended, but it might be useful to mention this in the README somewhere. (Or perhaps this issue itself is sufficient "documentation".)

(One reason why you might end up piping accept-encoding headers to probe-image-size is if the original input was something like Chrome DevTools' "Copy as cURL" function, which bulk copies all headers.)

AVIF support

Hi,

Is it on your plans to support avif format? Do you have an ETA?

Problem working through proxy

This works great until I try to add an agent to the options so that I can use this through a proxy.

const options = { agent: new HttpsProxyAgent(proxyUrl) };
const result = await probe(imageUrl, options);

I've traced this through the code. The first problem is that when you merge the options with default options, you also merge that with the URL, and this causes an immediate problem. But if I change your code so that line 34 of http.js becomes:

stream = request(src, merge.all([default, options]));

That allows my options to make it through. The problem then appears on line 751 of request.js:

self.req = self.httpModule.request(reqOptions)

At this point, I can see the that reqOptions object appears to be correct. It has an "agent" member that is an object and looks right. But this always throws an error saying,

"The "options.agent" property must be one of Agent-like Object, undefined, or false. Received an instance of Object"

I can pass this same agent object into node-fetch as an option and it works correctly.

I'm using 2.88.2 of the request package in node v12.16.2. This is probe-image-size v5.0.0.

In browser?

Hey

I'd like to use this in the browser as a standalone package? Is this possible?

Thanks

Sync Usage?

Hey.. i need to implement this with sync
how to use the snippet provided in the readme.?

404 status code

For url: https://code-maven.com/stack-trace-in-javascript/img/code_maven_128.png

I got 404 error:

      at DuplexWrapper.<anonymous> (.../node_modules/probe-image-size/http.js:50:16)
      at emitThree (events.js:140:20)
      at DuplexWrapper.emit (events.js:216:7)
      at EventEmitter.ee.on.res (.../node_modules/probe-image-size/node_modules/got/index.js:250:10)
      at emitOne (events.js:115:13)
      at EventEmitter.emit (events.js:210:7)
      at Immediate.setImmediate (.../node_modules/probe-image-size/node_modules/got/index.js:99:8)
      at runCallback (timers.js:781:20)
      at tryOnImmediate (timers.js:743:5)
      at processImmediate [as _immediateCallback] (timers.js:714:5)```

Version without fs dependency?

Thanks a lot for this nice package!

Would it be possible for you to make a version without fs dependency? If you probe image size from an url stream, you don't need fs. Currently I cannot use this package in serverless lambda functions because of this dependency. The package buffer-image-size is a good example of a similar approach without fs.

Thanks for your consideration.

ProbeError: unrecognized file format

Environment: node 14.15.1 on Windows 10
probe-image-size: 7.1.0

Stacktrace:

   at ParserStream.parserEnd (my-repo\node_modules\probe-image-size\stream.js:39:28)
    at Object.onceWrapper (events.js:421:28)
    at ParserStream.emit (events.js:315:20)
    at endReadableNT (_stream_readable.js:1327:12)
    at processTicksAndRejections (internal/process/task_queues.js:80:21)

Code used:

import probeImageSize from 'probe-image-size';

const result = await probeImageSize("https://upload.wikimedia.org/wikipedia/commons/e/e7/Obcine_Slovenija_2007_Sveti_Jurij_v_Slovenskih_goricah.svg");

HEIC support

Hello, our customers upload more and more HEIC pictures from their phones. Will this format be supported in a future version?
heic

Unzip error after version 3.1.0

Description

I upgrade from 3.0.0 to 3.1.0 and I get a new error related to unzip operations. Do you know if there is a regression linked to new dependencies?
I noticed, unzip-response is not used anymore in 3.1.0 and my exception is linked to unzip operations.

I attach logs.

Comparing dependencies

+-- [email protected] |   | 350 | +-- [email protected]
-- | -- | -- | --
  | 352 | \| +-- [email protected] |   | 351 | \| +-- [email protected]
  | 353 | \| +-- [email protected] |   | 352 | \| +-- [email protected]
  | 354 | \| +-- [email protected] |   | 353 | \| +-- [email protected]
  | 355 | \| \| +-- [email protected] |   | 354 | \| \| +-- [email protected]
  | 356 | \| \| \| `-- [email protected] |   | 355 | \| \| \| `-- [email protected]
  | 357 | \| \| +-- [email protected] |   | 356 | \| \| +-- [email protected]
  | 358 | \| \| +-- [email protected] |   | 357 | \| \| +-- [email protected]
  | 359 | \| \| +-- [email protected] |   | 358 | \| \| +-- [email protected]
  | 360 | \| \| +-- [email protected] |   | 359 | \| \| +-- [email protected]
  | 361 | \| \| +-- [email protected] |   | 360 | \| \| +-- [email protected]
  |   |   |   | 361 | \| \| +-- [email protected]
  |   |   |   | 362 | \| \| \| +-- [email protected]
  |   |   |   | 363 | \| \| \| \| `-- [email protected]
  |   |   |   | 364 | \| \| \| `-- [email protected]
  | 362 | \| \| +-- [email protected] |   | 365 | \| \| +-- [email protected]
  |   |   |   | 366 | \| \| +-- [email protected]
  |   |   |   | 367 | \| \| +-- [email protected]
  |   |   |   | 368 | \| \| \| `-- [email protected]
  | 363 | \| \| +-- [email protected] |   | 369 | \| \| +-- [email protected]
  | 364 | \| \| +-- [email protected] |   |   |  
  | 365 | \| \| `-- [email protected] |   | 370 | \| \| +-- [email protected]
  | 366 | \| \|   `-- [email protected] |   | 371 | \| \| \| `-- [email protected]
  |   |   |   | 372 | \| \| `-- [email protected]
  | 367 | \| +-- [email protected] |   | 373 | \| +-- [email protected]
  | 368 | \| +-- [email protected] |   | 374 | \| +-- [email protected]
  | 369 | \| `-- [email protected]

Logs

In 3.0.0

2017-08-14T18:26:17.401978+00:00 app[web.1]:     at DuplexWrapper.<anonymous> (/app/node_modules/probe-image-size/http.js:50:16)
2017-08-14T18:26:17.401979+00:00 app[web.1]:     at emitThree (events.js:121:20)
2017-08-14T18:26:17.401980+00:00 app[web.1]:     at DuplexWrapper.emit (events.js:194:7)
2017-08-14T18:26:17.401981+00:00 app[web.1]:     at EventEmitter.ee.on.res (/app/node_modules/got/index.js:250:10)
2017-08-14T18:26:17.401982+00:00 app[web.1]:     at emitOne (events.js:96:13)
2017-08-14T18:26:17.401982+00:00 app[web.1]:     at EventEmitter.emit (events.js:188:7)
2017-08-14T18:26:17.401983+00:00 app[web.1]:     at Immediate.setImmediate (/app/node_modules/got/index.js:99:8)
2017-08-14T18:26:17.401987+00:00 app[web.1]:     at Immediate.wrapped (/app/node_modules/newrelic/lib/transaction/tracer/index.js:184:28)
2017-08-14T18:26:17.401988+00:00 app[web.1]:     at runCallback (timers.js:649:20)
2017-08-14T18:26:17.401988+00:00 app[web.1]:     at tryOnImmediate (timers.js:622:5)
2017-08-14T18:26:17.401989+00:00 app[web.1]:     at processImmediate [as _immediateCallback] (timers.js:594:5)

In 3.1.0

2017-08-14T18:26:17.401978+00:00 app[web.1]:     at DuplexWrapper.<anonymous> (/app/node_modules/probe-image-size/http.js:50:16)
2017-08-14T18:26:17.401979+00:00 app[web.1]:     at emitThree (events.js:121:20)
2017-08-14T18:26:17.401980+00:00 app[web.1]:     at DuplexWrapper.emit (events.js:194:7)
2017-08-14T18:26:17.401981+00:00 app[web.1]:     at EventEmitter.ee.on.res (/app/node_modules/got/index.js:250:10)
2017-08-14T18:26:17.401982+00:00 app[web.1]:     at emitOne (events.js:96:13)
2017-08-14T18:26:17.401982+00:00 app[web.1]:     at EventEmitter.emit (events.js:188:7)
2017-08-14T18:26:17.401983+00:00 app[web.1]:     at Immediate.setImmediate (/app/node_modules/got/index.js:99:8)
2017-08-14T18:26:17.401987+00:00 app[web.1]:     at Immediate.wrapped (/app/node_modules/newrelic/lib/transaction/tracer/index.js:184:28)
2017-08-14T18:26:17.401988+00:00 app[web.1]:     at runCallback (timers.js:649:20)
2017-08-14T18:26:17.401988+00:00 app[web.1]:     at tryOnImmediate (timers.js:622:5)
2017-08-14T18:26:17.401989+00:00 app[web.1]:     at processImmediate [as _immediateCallback] (timers.js:594:5)
2017-08-14T18:26:17.411162+00:00 app[web.1]: Mon Aug 14 2017 18:26:17 GMT+0000 (UTC) - error: app.js uncaughtException App will be exit(1) Error: write after end
2017-08-14T18:26:17.411165+00:00 app[web.1]:     at writeAfterEnd (_stream_writable.js:193:12)
2017-08-14T18:26:17.411166+00:00 app[web.1]:     at Unzip.Writable.write (_stream_writable.js:244:5)
2017-08-14T18:26:17.411167+00:00 app[web.1]:     at IncomingMessage.ondata (_stream_readable.js:555:20)
2017-08-14T18:26:17.411168+00:00 app[web.1]:     at emitOne (events.js:96:13)
2017-08-14T18:26:17.411168+00:00 app[web.1]:     at IncomingMessage.emit (events.js:188:7)
2017-08-14T18:26:17.411169+00:00 app[web.1]:     at IncomingMessage.wrapped (/app/node_modules/newrelic/lib/transaction/tracer/index.js:184:28)
2017-08-14T18:26:17.411170+00:00 app[web.1]:     at IncomingMessage.wrappedResponseEmit [as emit] (/app/node_modules/newrelic/lib/transaction/tracer/instrumentation/outbound.js:99:26)
2017-08-14T18:26:17.411171+00:00 app[web.1]:     at readableAddChunk (_stream_readable.js:176:18)
2017-08-14T18:26:17.411171+00:00 app[web.1]:     at PassThrough.Readable.push (_stream_readable.js:134:10)
2017-08-14T18:26:17.411171+00:00 app[web.1]:     at PassThrough.Transform.push (_stream_transform.js:128:32)
2017-08-14T18:26:17.411172+00:00 app[web.1]:     at afterTransform (_stream_transform.js:77:12)
2017-08-14T18:26:17.411173+00:00 app[web.1]:     at TransformState.afterTransform (_stream_transform.js:54:12)
2017-08-14T18:26:17.411173+00:00 app[web.1]:     at PassThrough._transform (_stream_passthrough.js:21:3)
2017-08-14T18:26:17.411173+00:00 app[web.1]:     at PassThrough.Transform._read (_stream_transform.js:167:10)
2017-08-14T18:26:17.411174+00:00 app[web.1]:     at PassThrough.Transform._write (_stream_transform.js:155:12)
2017-08-14T18:26:17.411174+00:00 app[web.1]:     at doWrite (_stream_writable.js:334:12)
2017-08-14T18:26:17.411175+00:00 app[web.1]:     at writeOrBuffer (_stream_writable.js:320:5)
2017-08-14T18:26:17.411175+00:00 app[web.1]:     at PassThrough.Writable.write (_stream_writable.js:247:11)
2017-08-14T18:26:17.411175+00:00 app[web.1]:     at Unzip.ondata (_stream_readable.js:555:20)
2017-08-14T18:26:17.411176+00:00 app[web.1]:     at emitOne (events.js:96:13)
2017-08-14T18:26:17.411176+00:00 app[web.1]:     at Unzip.emit (events.js:188:7)
2017-08-14T18:26:17.411176+00:00 app[web.1]:     at readableAddChunk (_stream_readable.js:176:18)
2017-08-14T18:26:17.411177+00:00 app[web.1]:     at Unzip.Readable.push (_stream_readable.js:134:10)
2017-08-14T18:26:17.411177+00:00 app[web.1]:     at Unzip.Transform.push (_stream_transform.js:128:32)
2017-08-14T18:26:17.411177+00:00 app[web.1]:     at Zlib.callback (zlib.js:598:14)

UnhandledPromiseRejectionWarning: Error: Invalid URI when i try to pass a local server image url to probe

http:\localhost:3000\api\uploads\5c8e8d81e51b0f3c7409b662\staffs-avatar\9qAnpXFHAOmAaQ9QKUG5tudJzGMk2KCi.jpg
(node:18724) UnhandledPromiseRejectionWarning: Error: Invalid URI "http:/localhost:3000/api/uploads/5c8e8d81e51b0f3c7409b662/staffs-avatar/9qAnpXFHAOmAaQ9QKUG5tudJzGMk2KCi.jpg"
at Request.init (C:\tution\backend-service-nodejs-mongodb\node_modules\request\request.js:273:31)
at new Request (C:\tution\backend-service-nodejs-mongodb\node_modules\request\request.js:127:8)
at request (C:\tution\backend-service-nodejs-mongodb\node_modules\request\index.js:53:10)
at C:\tution\backend-service-nodejs-mongodb\node_modules\probe-image-size\http.js:31:13
at new Promise ()
at probeHttp (C:\tution\backend-service-nodejs-mongodb\node_modules\probe-image-size\http.js:27:10)
at get_image_size (C:\tution\backend-service-nodejs-mongodb\node_modules\probe-image-size\index.js:42:25)
at Promise.all.subdirs.map (C:\tution\backend-service-nodejs-mongodb\src\routes\staffs.js:64:13)
at Array.map ()
at getFiles (C:\tution\backend-service-nodejs-mongodb\src\routes\staffs.js:58:17)
(node:18724) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

Probe hanging without any error

Hi there,

I have a function that is used to upload images to S3

async function uploadToBucket(options={}) {
  Sentry.addBreadcrumb({category: 'async'})

  const {bucket, stream: body, file, extension, mimetype} = options
  const filename = filenameHandler(file, extension)

  const m = meter()
  const s3Stream = new stream.PassThrough()
  const dimensionStream = new stream.PassThrough()
  body
    .pipe(m)
    .pipe(s3Stream)

  body.pipe(dimensionStream)

  const {width, height} = await probe(dimensionStream)

  const s3Upload = await s3.upload({
    Bucket: bucket,
    Key: filename,
    Body: body,
    ContentType: mimetype,
  })
    .promise()
    .then(res => {
      return {
        filename,
        mimetype,
        size: m.bytes,
        width,
        height
      }
    })
    .catch(error => {
      logger.error(`S3 Failed: ${error}`)
    })

  return s3Upload
}

This has been working well with basically anything we've thrown at it. Except for this one image that wouldn't get uploaded. After some debugging I saw that the line where the upload to S3 is actually done would never be reached. Commenting out const {width, height} = await probe(dimensionStream) would make the upload work.

I tried wrapping probe in a try/catch block but to avail as no error is thrown. Probe just seems to be hanging. Any idea of what may be happening?

FYI this is the image that is creating this issue
air-pollution

How does this library work?

How does this library work as in what's the technical background behind it and not how you use it?

I'd love to understand how that library works behind the scenes but I'm having some difficulties understanding what's going on in the source code. Can anybody shed a little light on this? 🤗

ProbeError: ECONTENT unrecognized file format

I am using [email protected] and I have the following code:

var probe = require('probe-image-size');
probe(url, function(err, res) {
    if (err) {
        console.error(err);
    }
});

I get the following error with this image: http://www.4usky.com/data/out/72/164647502-porsche-cayenne-wallpapers.jpg

{ Error
    at Transform.parserEnd (C:\project\node_modules\probe-image-size\stream.js:29:24)
    at Object.onceWrapper (events.js:291:19)
    at emitNone (events.js:91:20)
    at Transform.emit (events.js:186:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
  name: 'ProbeError',
  message: 'unrecognized file format',
  code: 'ECONTENT' }

Cannot read property 'end' on stream during cleanup

Hi there,
I'm having trouble getting to a bottom of an error that has come up using this library in my application. The package version I'm using is 1.2.1 and the error seems to be happening at this location in stream.js. I've also only found it to happen in the gif.js file. This output is from Bugsnag and it's not catching the image that it's probing so I'm unsure which file is causing this issue. I'm curious if someone may have some insight into what is causing this or how I could potentially catch this error and surface what image is causing it?

Thanks!

TypeError Cannot read property 'end' of undefined 
    node_modules/probe-image-size/stream.js:39:20 cleanup
    node_modules/probe-image-size/stream.js:62:7 none
    node_modules/probe-image-size/lib/common.js:25:10 none
    node_modules/probe-image-size/lib/parse_stream/gif.js:22:7 none
    node_modules/stream-parser/index.js:270:20 process
    node_modules/stream-parser/index.js:204:14 none
    node_modules/stream-parser/index.js:294:16 none
    node_modules/stream-parser/index.js:176:3 transform [as _transform]
    node_modules/probe-image-size/node_modules/readable-stream/lib/_stream_transform.js:159:10 Transform._read
    node_modules/probe-image-size/node_modules/readable-stream/lib/_stream_transform.js:147:83 Transform._write
    node_modules/probe-image-size/node_modules/readable-stream/lib/_stream_writable.js:319:64 doWrite
    node_modules/probe-image-size/node_modules/readable-stream/lib/_stream_writable.js:308:5 writeOrBuffer
    node_modules/probe-image-size/node_modules/readable-stream/lib/_stream_writable.js:246:11 Writable.write
    _stream_readable.js:561:20 ondata
    events.js:101:20 emitOne
    events.js:188:7 emit
    _stream_readable.js:387:10 Readable.read
    _stream_readable.js:772:26 flow
    _stream_readable.js:752:3 resume_
    internal/process/next_tick.js:74:11 _combinedTickCallback
    internal/process/next_tick.js:122:9 _tickDomainCallback

request package is deprecated, consider replacing with an alternative like node-fetch

The request package has been deprecated. This package only seems to use it in the http.js file, the advice appears to migrate to an alternative like node-fetch.

stream = request(merge.all([ { url: src }, defaults, options ]));

finalUrl = res.request.uri.href;

I'm not raising the issue due to any bug or vulnerabilities, just making you aware of the deprecation as it is raised as a warning during package installs:

warning gatsby-plugin-sharp > probe-image-size > [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142

Cheers.

Add GIF support

Title, this would be really helpful for my program, as it occasionally tries to find GIFs too

Add JPEG XR Support

The service I'm working on serves smaller JPEG XR images to browsers which support them, and it'd be useful to be able to report their dimensions too.

Would you be interested in adding this feature, or accepting a PR?

Unpredictable socket hang ups with status code ECONNRESET

Description

Successively probing the image size of a remote image always leads to a socket hang up after a couple of minutes. The number of probes it takes until the socket hang up occurs vary, but it always occurs in my test if I just wait long enough. Sometimes it takes just a hand-full iterations, other times it takes several hundred of iterations. Both the client and the server seem to be waiting until the client gives up with the following error message:

Error: socket hang up
    at connResetException (node:internal/errors:629:14)
    at TLSSocket.socketCloseListener (node:_http_client:451:25)
    at TLSSocket.emit (node:events:341:22)
    at node:net:655:12
    at TCP.done (node:_tls_wrap:564:7) {
  code: 'ECONNRESET'

The server is serving a static file with nginx and the logs do not show anything peculiar:

2020/11/22 00:06:55 [warn] 213383#0: *1712 an upstream response is buffered to a temporary file /var/lib/nginx/tmp/proxy/5/85/0000000855 while reading upstream, client: 37.201.193.119, server: static.gotsby.org, request: "GET /v1/assets/images/creating-a-custom-theme.png HTTP/1.1", upstream: "http://127.0.0.1:7000/v1/assets/images/creating-a-custom-theme.png", host: "static.gotsby.org"
2020/11/22 00:06:55 [info] 213383#0: *1712 client prematurely closed connection (104: Connection reset by peer) while sending to client, client: 37.201.193.119, server: static.gotsby.org, request: "GET /v1/assets/images/creating-a-custom-theme.png HTTP/1.1", upstream: "http://127.0.0.1:7000/v1/assets/images/creating-a-custom-theme.png", host: "static.gotsby.org"
2020/11/22 00:06:55 [warn] 213383#0: *1714 an upstream response is buffered to a temporary file /var/lib/nginx/tmp/proxy/6/85/0000000856 while reading upstream, client: 37.201.193.119, server: static.gotsby.org, request: "GET /v1/assets/images/creating-a-custom-theme.png HTTP/1.1", upstream: "http://127.0.0.1:7000/v1/assets/images/creating-a-custom-theme.png", host: "static.gotsby.org"
2020/11/22 00:06:55 [info] 213383#0: *1714 client prematurely closed connection (32: Broken pipe) while sending to client, client: 37.201.193.119, server: static.gotsby.org, request: "GET /v1/assets/images/creating-a-custom-theme.png HTTP/1.1", upstream: "http://127.0.0.1:7000/v1/assets/images/creating-a-custom-theme.png", host: "static.gotsby.org"

The client error comes 60 seconds after the last server log message. Note that the error always occurs on a "(32: Broken pipe)" while I also see "(104: Connection reset by peer)". However, the broken pipe message also appears in cases that do not lead to a socket hang up.

How to reproduce

git clone https://github.com/styxlab/image-probe-test.git
cd image-probe-test
yarn
node test

This will run an infinite loop probing an image on a remote server that I control. The test can be changed to probe an image on localhost. However, the issue did not occur when testing on localhost.

Other info

I checked that the firewall is not getting in the way by disabling it completely.

Client Environment

Linux home 5.9.8-100.fc32.x86_64
node v15.2.1

Thanks for this great repo!
-- styxlab

ERR_STREAM_PUSH_AFTER_EOF in probe-image-size/lib/parse_stream/svg.js:163:20

Test case (test.js):

let probe = require("probe-image-size");
let Promise = require("bluebird");
let axios = require("axios");
let server = require("express")();

server.post("/probe", async function(req, res)
{
	await new Promise(resolve => setImmediate(resolve));
	await probe(req);
	res.end();
});

let request = axios.create({ baseURL: "http://127.0.0.1:8888", validateStatus: null, maxRedirects: 0 });

let svg = `<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100pt" height="100pt" viewBox="0 0 100 100" version="1.1">`;
for(let i = 0; i < 100000; i++) svg += " ";

async function main()
{
	await new Promise(resolve => server.listen(8888, resolve));
	while(true) await request.post("/probe", svg).catch(() => {});
}

main();

Install and run (it may take some time):

npm install probe-image-size bluebird axios express
node test.js

Possible output:

events.js:292
      throw er; // Unhandled 'error' event
      ^

Error [ERR_STREAM_PUSH_AFTER_EOF]: stream.push() after EOF
    at readableAddChunk (internal/streams/readable.js:272:30)
    at Transform.Readable.push (internal/streams/readable.js:223:10)
    at Transform.push (internal/streams/transform.js:166:32)
    at Transform.transform [as _transform] (.../node_modules/probe-image-size/lib/parse_stream/svg.js:163:20)
    at Transform._read (internal/streams/transform.js:205:10)
    at Transform._write (internal/streams/transform.js:193:12)
    at writeOrBuffer (internal/streams/writable.js:358:12)
    at Transform.Writable.write (internal/streams/writable.js:303:10)
    at PassThrough.ondata (internal/streams/readable.js:719:22)
    at PassThrough.emit (events.js:327:22)
    at addChunk (internal/streams/readable.js:309:12)
    at readableAddChunk (internal/streams/readable.js:284:9)
    at PassThrough.Readable.push (internal/streams/readable.js:223:10)
    at PassThrough.Transform.push (internal/streams/transform.js:166:32)
    at PassThrough.afterTransform (internal/streams/transform.js:101:10)
    at PassThrough._transform (internal/streams/passthrough.js:46:3)
Emitted 'error' event on Transform instance at:
    at emitErrorNT (internal/streams/destroy.js:106:8)
    at emitErrorCloseNT (internal/streams/destroy.js:74:3)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  code: 'ERR_STREAM_PUSH_AFTER_EOF'
}

ProbeError: unrecognized file format

Same error as in #57, but different image:

Stacktrace:

   at ParserStream.parserEnd (my-repo\node_modules\probe-image-size\stream.js:39:28)
    at Object.onceWrapper (events.js:421:28)
    at ParserStream.emit (events.js:315:20)
    at endReadableNT (_stream_readable.js:1327:12)
    at processTicksAndRejections (internal/process/task_queues.js:80:21)

Code used:

import probeImageSize from 'probe-image-size';

const result = await probeImageSize("https://upload.wikimedia.org/wikipedia/commons/8/82/Scotland_in_the_UK_and_Europe.svg");

Environment: node 14.15.1 on Windows 10
probe-image-size: 7.1.1

Other images that have the same problem:

https://upload.wikimedia.org/wikipedia/commons/3/3a/Locator_map_of_Azores_in_EU.svg
https://upload.wikimedia.org/wikipedia/commons/3/3e/EU-Portugal_with_Madeira_circled.svg
https://upload.wikimedia.org/wikipedia/commons/5/55/Gibraltar_location_in_Europe.svg

dist is too big!

I create a vue cli3 program with webpack-bundle-analyzer installing.
The chunk-vendors.js is up to 1.16M after import probe-image-size package while the origin chunk-vendors.js is 110.23KB.
I test another package image-size which is mentioned in your readme file, the final chunk-vendors.js is 155.47KB.

After import probe-image-size, webpack-bundle-analyzer shows there are a lot of packages using the same package bn.js. That's weird.

Unrecognized FIle Format Error

Hi,

I want dimension of following attached Image. But it giving me following error:

ProbeError: unrecognized file format
name: 'ProbeError',
message: 'unrecognized file format',
code: 'ECONTENT' }

here is my code

`var probe = require('probe-image-size');
var fs = require('fs')

return probe('https://images.contentstack.io/v3/assets/blt37054b6140c1853d/bltdcad91c964a7688a/5fc6577a09ed4c6f277f1b2d/dleta.jpeg').then(function (result) {
console.log("Done",result)
}).catch(function (error) {
console.log("Error",error)
})`

Kindly help me here.

guard-buckingham-200x300_(1)

ECONTENT unrecognized file format

node node_modules/probe-image-size/support/dump.js 
![gefuellte-paprika-1](https://user-images.githubusercontent.com/5196971/36979931-ea8bd92c-2056-11e8-9161-63f3e19e2a6f.jpg)
gefuellte-paprika-1.jpg
{ ProbeError: unrecognized file format
    at ParserStream.parserEnd (/Users/Can/Sites/react/gaiama-gatsby-content/happygaia-export/node_modules/probe-image-size/stream.js:29:24)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:111:20)
    at ParserStream.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1055:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
  name: 'ProbeError',
  message: 'unrecognized file format',
  code: 'ECONTENT' }

maybe it's because of this?

Note. Formats like JPEG & TIFF can store size anywhere (far from the head).

I'm using gatsbyjs where gatsby-plugin-sharp includes your module and only this one image errored, I could fix it for now by resaving it
just opening the issue to let you know and understand whats going on ;-)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.