file-type 21.3.3 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +36 -53
- package/readme.md +35 -105
- package/source/detectors/asf.js +127 -0
- package/source/detectors/ebml.js +120 -0
- package/source/detectors/png.js +123 -0
- package/source/detectors/zip.js +643 -0
- package/{core.d.ts → source/index.d.ts} +49 -22
- package/{core.js → source/index.js} +242 -1122
- package/source/index.test-d.ts +53 -0
- package/source/parser.js +65 -0
- package/{supported.js → source/supported.js} +14 -6
- package/{util.js → source/tokens.js} +2 -2
- package/index.d.ts +0 -98
- package/index.js +0 -126
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {ReadableStream as NodeReadableStream} from 'node:stream/web';
|
|
2
|
+
import {expectType} from 'tsd';
|
|
3
|
+
import {
|
|
4
|
+
type FileTypeResult,
|
|
5
|
+
type FileTypeResult as FileTypeResultBrowser,
|
|
6
|
+
type AnyWebReadableByteStreamWithFileType,
|
|
7
|
+
fileTypeFromBlob,
|
|
8
|
+
fileTypeFromBuffer,
|
|
9
|
+
fileTypeFromFile,
|
|
10
|
+
fileTypeFromStream,
|
|
11
|
+
fileTypeStream,
|
|
12
|
+
FileTypeParser,
|
|
13
|
+
} from './index.js';
|
|
14
|
+
|
|
15
|
+
// `fileTypeStream`: accepts StreamOptions & FileTypeOptions
|
|
16
|
+
(async () => {
|
|
17
|
+
const webStream = new ReadableStream<Uint8Array>();
|
|
18
|
+
expectType<AnyWebReadableByteStreamWithFileType>(await fileTypeStream(webStream, {sampleSize: 256}));
|
|
19
|
+
expectType<AnyWebReadableByteStreamWithFileType>(await fileTypeStream(webStream, {sampleSize: 256, customDetectors: []}));
|
|
20
|
+
expectType<AnyWebReadableByteStreamWithFileType>(await fileTypeStream(webStream, {signal: AbortSignal.timeout(1000)}));
|
|
21
|
+
})();
|
|
22
|
+
|
|
23
|
+
// `FileTypeParser`: tests generic input types and options
|
|
24
|
+
(async () => {
|
|
25
|
+
const fileTypeParser = new FileTypeParser({customDetectors: [], signal: AbortSignal.timeout(1000)});
|
|
26
|
+
const fileTypeParserWithMpeg = new FileTypeParser({mpegOffsetTolerance: 10});
|
|
27
|
+
const webStream = new ReadableStream<Uint8Array>();
|
|
28
|
+
const nodeWebStream = new NodeReadableStream<Uint8Array>();
|
|
29
|
+
|
|
30
|
+
expectType<FileTypeResult | undefined>(await fileTypeParser.fromStream(webStream));
|
|
31
|
+
expectType<FileTypeResult | undefined>(await fileTypeParser.fromStream(nodeWebStream));
|
|
32
|
+
|
|
33
|
+
expectType<AnyWebReadableByteStreamWithFileType>(await fileTypeParser.toDetectionStream(webStream, {sampleSize: 256}));
|
|
34
|
+
})();
|
|
35
|
+
|
|
36
|
+
// `fileTypeFromStream`: accepts FileTypeOptions
|
|
37
|
+
(async () => {
|
|
38
|
+
const webStream = new ReadableStream<Uint8Array>();
|
|
39
|
+
expectType<FileTypeResult | undefined>(await fileTypeFromStream(webStream, {signal: AbortSignal.timeout(1000)}));
|
|
40
|
+
})();
|
|
41
|
+
|
|
42
|
+
// Test that Blob overload returns browser-specific result
|
|
43
|
+
expectType<Promise<FileTypeResultBrowser | undefined>>(fileTypeFromBlob(new Blob([])));
|
|
44
|
+
|
|
45
|
+
// `fileTypeFromFile`: accepts a file path and options
|
|
46
|
+
expectType<Promise<FileTypeResult | undefined>>(fileTypeFromFile('file.bin'));
|
|
47
|
+
expectType<Promise<FileTypeResult | undefined>>(fileTypeFromFile('file.bin', {signal: AbortSignal.timeout(1000)}));
|
|
48
|
+
|
|
49
|
+
// `FileTypeParser#fromFile`: accepts a file path
|
|
50
|
+
(async () => {
|
|
51
|
+
const fileTypeParser = new FileTypeParser();
|
|
52
|
+
expectType<Promise<FileTypeResult | undefined>>(fileTypeParser.fromFile('file.bin'));
|
|
53
|
+
})();
|
package/source/parser.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export const maximumUntrustedSkipSizeInBytes = 16 * 1024 * 1024;
|
|
2
|
+
|
|
3
|
+
export class ParserHardLimitError extends Error {}
|
|
4
|
+
|
|
5
|
+
export function getSafeBound(value, maximum, reason) {
|
|
6
|
+
if (
|
|
7
|
+
!Number.isFinite(value)
|
|
8
|
+
|| value < 0
|
|
9
|
+
|| value > maximum
|
|
10
|
+
) {
|
|
11
|
+
throw new ParserHardLimitError(`${reason} has invalid size ${value} (maximum ${maximum} bytes)`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function safeIgnore(tokenizer, length, {maximumLength = maximumUntrustedSkipSizeInBytes, reason = 'skip'} = {}) {
|
|
18
|
+
const safeLength = getSafeBound(length, maximumLength, reason);
|
|
19
|
+
await tokenizer.ignore(safeLength);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function safeReadBuffer(tokenizer, buffer, options, {maximumLength = buffer.length, reason = 'read'} = {}) {
|
|
23
|
+
const length = options?.length ?? buffer.length;
|
|
24
|
+
const safeLength = getSafeBound(length, maximumLength, reason);
|
|
25
|
+
return tokenizer.readBuffer(buffer, {
|
|
26
|
+
...options,
|
|
27
|
+
length: safeLength,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function checkBytes(buffer, headers, options) {
|
|
32
|
+
options = {
|
|
33
|
+
offset: 0,
|
|
34
|
+
...options,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
for (const [index, header] of headers.entries()) {
|
|
38
|
+
// If a bitmask is set
|
|
39
|
+
if (options.mask) {
|
|
40
|
+
// If header doesn't equal `buf` with bits masked off
|
|
41
|
+
if (header !== (options.mask[index] & buffer[index + options.offset])) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
} else if (header !== buffer[index + options.offset]) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function hasUnknownFileSize(tokenizer) {
|
|
53
|
+
const fileSize = tokenizer.fileInfo.size;
|
|
54
|
+
return (
|
|
55
|
+
!Number.isFinite(fileSize)
|
|
56
|
+
|| fileSize === Number.MAX_SAFE_INTEGER
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function hasExceededUnknownSizeScanBudget(tokenizer, startOffset, maximumBytes) {
|
|
61
|
+
return (
|
|
62
|
+
hasUnknownFileSize(tokenizer)
|
|
63
|
+
&& tokenizer.position - startOffset > maximumBytes
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// MIME media subtypes prefixed with `x-ft-` are custom and defined by us. They are neither formally registered with IANA nor based on any informal conventions.
|
|
2
|
+
|
|
1
3
|
export const extensions = [
|
|
2
4
|
'jpg',
|
|
3
5
|
'png',
|
|
@@ -179,6 +181,9 @@ export const extensions = [
|
|
|
179
181
|
'tar.gz',
|
|
180
182
|
'reg',
|
|
181
183
|
'dat',
|
|
184
|
+
'key',
|
|
185
|
+
'numbers',
|
|
186
|
+
'pages',
|
|
182
187
|
];
|
|
183
188
|
|
|
184
189
|
export const mimeTypes = [
|
|
@@ -262,7 +267,7 @@ export const mimeTypes = [
|
|
|
262
267
|
'application/x-unix-archive',
|
|
263
268
|
'application/x-rpm',
|
|
264
269
|
'application/x-compress',
|
|
265
|
-
'application/
|
|
270
|
+
'application/lzip',
|
|
266
271
|
'application/x-cfb',
|
|
267
272
|
'application/x-mie',
|
|
268
273
|
'application/mxf',
|
|
@@ -291,8 +296,8 @@ export const mimeTypes = [
|
|
|
291
296
|
'model/gltf-binary',
|
|
292
297
|
'application/vnd.tcpdump.pcap',
|
|
293
298
|
'audio/x-dsf', // Non-standard
|
|
294
|
-
'application/x
|
|
295
|
-
'application/x
|
|
299
|
+
'application/x-ms-shortcut', // Informal, used by freedesktop.org shared-mime-info
|
|
300
|
+
'application/x-ft-apple.alias',
|
|
296
301
|
'audio/x-voc',
|
|
297
302
|
'audio/vnd.dolby.dd-raw',
|
|
298
303
|
'audio/x-m4a',
|
|
@@ -332,11 +337,11 @@ export const mimeTypes = [
|
|
|
332
337
|
'application/x-ace-compressed',
|
|
333
338
|
'application/avro',
|
|
334
339
|
'application/vnd.iccprofile',
|
|
335
|
-
'application/x
|
|
340
|
+
'application/x-ft-fbx',
|
|
336
341
|
'application/vnd.visio',
|
|
337
342
|
'application/vnd.android.package-archive',
|
|
338
|
-
'application/
|
|
339
|
-
'application/x-lz4', //
|
|
343
|
+
'application/x-ft-draco',
|
|
344
|
+
'application/x-lz4', // Informal, used by freedesktop.org shared-mime-info
|
|
340
345
|
'application/vnd.openxmlformats-officedocument.presentationml.template',
|
|
341
346
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
|
342
347
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
|
@@ -357,4 +362,7 @@ export const mimeTypes = [
|
|
|
357
362
|
'application/x-ms-regedit',
|
|
358
363
|
'application/x-ft-windows-registry-hive',
|
|
359
364
|
'application/x-jmp-data',
|
|
365
|
+
'application/vnd.apple.keynote',
|
|
366
|
+
'application/vnd.apple.numbers',
|
|
367
|
+
'application/vnd.apple.pages',
|
|
360
368
|
];
|
|
@@ -32,7 +32,7 @@ Checks whether the TAR checksum is valid.
|
|
|
32
32
|
@returns {boolean} `true` if the TAR checksum is valid, otherwise `false`.
|
|
33
33
|
*/
|
|
34
34
|
export function tarHeaderChecksumMatches(arrayBuffer, offset = 0) {
|
|
35
|
-
const readSum = Number.parseInt(new StringType(6).get(arrayBuffer, 148).replace(/\0
|
|
35
|
+
const readSum = Number.parseInt(new StringType(6).get(arrayBuffer, 148).replace(/\0.*$/v, '').trim(), 8); // Read sum in header
|
|
36
36
|
if (Number.isNaN(readSum)) {
|
|
37
37
|
return false;
|
|
38
38
|
}
|
|
@@ -55,6 +55,6 @@ ID3 UINT32 sync-safe tokenizer token.
|
|
|
55
55
|
28 bits (representing up to 256MB) integer, the msb is 0 to avoid "false syncsignals".
|
|
56
56
|
*/
|
|
57
57
|
export const uint32SyncSafeToken = {
|
|
58
|
-
get: (buffer, offset) => (buffer[offset + 3] & 0x7F) | ((buffer[offset + 2]) << 7) | ((buffer[offset + 1]) << 14) | ((buffer[offset]) << 21),
|
|
58
|
+
get: (buffer, offset) => (buffer[offset + 3] & 0x7F) | ((buffer[offset + 2] & 0x7F) << 7) | ((buffer[offset + 1] & 0x7F) << 14) | ((buffer[offset] & 0x7F) << 21),
|
|
59
59
|
len: 4,
|
|
60
60
|
};
|
package/index.d.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
Typings for Node.js specific entry point.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type {Readable as NodeReadableStream} from 'node:stream';
|
|
6
|
-
import type {AnyWebByteStream} from 'strtok3';
|
|
7
|
-
import {
|
|
8
|
-
type FileTypeResult,
|
|
9
|
-
type StreamOptions,
|
|
10
|
-
type AnyWebReadableStream,
|
|
11
|
-
type AnyWebReadableByteStreamWithFileType,
|
|
12
|
-
type FileTypeOptions,
|
|
13
|
-
FileTypeParser as DefaultFileTypeParser,
|
|
14
|
-
} from './core.js';
|
|
15
|
-
|
|
16
|
-
export type ReadableStreamWithFileType = NodeReadableStream & {
|
|
17
|
-
readonly fileType?: FileTypeResult;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
Extending `FileTypeParser` with Node.js engine specific functions.
|
|
22
|
-
*/
|
|
23
|
-
export declare class FileTypeParser extends DefaultFileTypeParser {
|
|
24
|
-
/**
|
|
25
|
-
@param stream - Node.js `stream.Readable` or web `ReadableStream`.
|
|
26
|
-
*/
|
|
27
|
-
fromStream(stream: AnyWebReadableStream<Uint8Array> | NodeReadableStream): Promise<FileTypeResult | undefined>;
|
|
28
|
-
|
|
29
|
-
fromFile(filePath: string): Promise<FileTypeResult | undefined>;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
Works the same way as {@link fileTypeStream}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
33
|
-
*/
|
|
34
|
-
toDetectionStream(readableStream: NodeReadableStream, options?: FileTypeOptions & StreamOptions): Promise<ReadableStreamWithFileType>;
|
|
35
|
-
toDetectionStream(webStream: AnyWebReadableStream<Uint8Array>, options?: FileTypeOptions & StreamOptions): Promise<AnyWebReadableByteStreamWithFileType>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
Detect the file type of a file path.
|
|
40
|
-
|
|
41
|
-
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the file.
|
|
42
|
-
|
|
43
|
-
This is for Node.js only.
|
|
44
|
-
|
|
45
|
-
To read from a [`File`](https://developer.mozilla.org/docs/Web/API/File), see `fileTypeFromBlob()`.
|
|
46
|
-
|
|
47
|
-
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
48
|
-
|
|
49
|
-
@returns The detected file type and MIME type or `undefined` when there is no match.
|
|
50
|
-
*/
|
|
51
|
-
export function fileTypeFromFile(filePath: string, options?: FileTypeOptions): Promise<FileTypeResult | undefined>;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
Detect the file type of a [web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
|
55
|
-
|
|
56
|
-
If the engine is Node.js, this may also be a [Node.js `stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable).
|
|
57
|
-
|
|
58
|
-
Direct support for Node.js streams will be dropped in the future, when Node.js streams can be converted to Web streams (see [`toWeb()`](https://nodejs.org/api/stream.html#streamreadabletowebstreamreadable-options)).
|
|
59
|
-
|
|
60
|
-
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
61
|
-
|
|
62
|
-
@param stream - A [web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) or [Node.js `stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable) streaming a file to examine.
|
|
63
|
-
@param options - Options to override default behaviour.
|
|
64
|
-
@returns A `Promise` for an object with the detected file type, or `undefined` when there is no match.
|
|
65
|
-
*/
|
|
66
|
-
export function fileTypeFromStream(stream: AnyWebReadableStream<Uint8Array> | NodeReadableStream, options?: FileTypeOptions): Promise<FileTypeResult | undefined>;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
70
|
-
|
|
71
|
-
This method can be handy to put in between a stream, but it comes with a price.
|
|
72
|
-
Internally `stream()` builds up a buffer of `sampleSize` bytes, used as a sample, to determine the file type.
|
|
73
|
-
The sample size impacts the file detection resolution.
|
|
74
|
-
A smaller sample size will result in lower probability of the best file type detection.
|
|
75
|
-
|
|
76
|
-
@param readableStream - A [web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) or [Node.js `stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable), streaming a file to examine.
|
|
77
|
-
@param options - May be used to override the default sample size.
|
|
78
|
-
@returns A `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
79
|
-
|
|
80
|
-
@example
|
|
81
|
-
```
|
|
82
|
-
import got from 'got';
|
|
83
|
-
import {fileTypeStream} from 'file-type';
|
|
84
|
-
|
|
85
|
-
const url = 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg';
|
|
86
|
-
|
|
87
|
-
const stream1 = got.stream(url);
|
|
88
|
-
const stream2 = await fileTypeStream(stream1, {sampleSize: 1024});
|
|
89
|
-
|
|
90
|
-
if (stream2.fileType?.mime === 'image/jpeg') {
|
|
91
|
-
// stream2 can be used to stream the JPEG image (from the very beginning of the stream)
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
*/
|
|
95
|
-
export function fileTypeStream(readableStream: NodeReadableStream, options?: FileTypeOptions & StreamOptions): Promise<ReadableStreamWithFileType>;
|
|
96
|
-
export function fileTypeStream(webStream: AnyWebByteStream, options?: FileTypeOptions & StreamOptions): Promise<AnyWebReadableByteStreamWithFileType>;
|
|
97
|
-
|
|
98
|
-
export * from './core.js';
|
package/index.js
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
Node.js specific entry point.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {ReadableStream as WebReadableStream} from 'node:stream/web';
|
|
6
|
-
import {pipeline, PassThrough, Readable} from 'node:stream';
|
|
7
|
-
import fs from 'node:fs/promises';
|
|
8
|
-
import {constants as fileSystemConstants} from 'node:fs';
|
|
9
|
-
import * as strtok3 from 'strtok3';
|
|
10
|
-
import {
|
|
11
|
-
FileTypeParser as DefaultFileTypeParser,
|
|
12
|
-
reasonableDetectionSizeInBytes,
|
|
13
|
-
normalizeSampleSize,
|
|
14
|
-
} from './core.js';
|
|
15
|
-
|
|
16
|
-
function isTokenizerStreamBoundsError(error) {
|
|
17
|
-
if (
|
|
18
|
-
!(error instanceof RangeError)
|
|
19
|
-
|| error.message !== 'offset is out of bounds'
|
|
20
|
-
|| typeof error.stack !== 'string'
|
|
21
|
-
) {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Some malformed or non-byte Node.js streams can surface this tokenizer-internal range error.
|
|
26
|
-
// Note: This stack-trace check is fragile and may break if strtok3 restructures its internals.
|
|
27
|
-
return /strtok3[/\\]lib[/\\]stream[/\\]/.test(error.stack);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class FileTypeParser extends DefaultFileTypeParser {
|
|
31
|
-
async fromStream(stream) {
|
|
32
|
-
const tokenizer = await (stream instanceof WebReadableStream ? strtok3.fromWebStream(stream, this.getTokenizerOptions()) : strtok3.fromStream(stream, this.getTokenizerOptions()));
|
|
33
|
-
try {
|
|
34
|
-
return await super.fromTokenizer(tokenizer);
|
|
35
|
-
} catch (error) {
|
|
36
|
-
if (isTokenizerStreamBoundsError(error)) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
throw error;
|
|
41
|
-
} finally {
|
|
42
|
-
await tokenizer.close();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async fromFile(path) {
|
|
47
|
-
// TODO: Remove this when `strtok3.fromFile()` safely rejects non-regular filesystem objects without a pathname race.
|
|
48
|
-
const fileHandle = await fs.open(path, fileSystemConstants.O_RDONLY | fileSystemConstants.O_NONBLOCK);
|
|
49
|
-
const fileStat = await fileHandle.stat();
|
|
50
|
-
if (!fileStat.isFile()) {
|
|
51
|
-
await fileHandle.close();
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const tokenizer = new strtok3.FileTokenizer(fileHandle, {
|
|
56
|
-
...this.getTokenizerOptions(),
|
|
57
|
-
fileInfo: {
|
|
58
|
-
path,
|
|
59
|
-
size: fileStat.size,
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
try {
|
|
63
|
-
return await super.fromTokenizer(tokenizer);
|
|
64
|
-
} finally {
|
|
65
|
-
await tokenizer.close();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async toDetectionStream(readableStream, options = {}) {
|
|
70
|
-
if (!(readableStream instanceof Readable)) {
|
|
71
|
-
return super.toDetectionStream(readableStream, options);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const sampleSize = normalizeSampleSize(options.sampleSize ?? reasonableDetectionSizeInBytes);
|
|
75
|
-
|
|
76
|
-
return new Promise((resolve, reject) => {
|
|
77
|
-
readableStream.on('error', reject);
|
|
78
|
-
|
|
79
|
-
readableStream.once('readable', () => {
|
|
80
|
-
(async () => {
|
|
81
|
-
try {
|
|
82
|
-
// Set up output stream
|
|
83
|
-
const pass = new PassThrough();
|
|
84
|
-
const outputStream = pipeline ? pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
|
|
85
|
-
|
|
86
|
-
// Read the input stream and detect the filetype
|
|
87
|
-
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? new Uint8Array(0);
|
|
88
|
-
try {
|
|
89
|
-
pass.fileType = await this.fromBuffer(chunk);
|
|
90
|
-
} catch (error) {
|
|
91
|
-
if (error instanceof strtok3.EndOfStreamError) {
|
|
92
|
-
pass.fileType = undefined;
|
|
93
|
-
} else {
|
|
94
|
-
reject(error);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
resolve(outputStream);
|
|
99
|
-
} catch (error) {
|
|
100
|
-
reject(error);
|
|
101
|
-
}
|
|
102
|
-
})();
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export async function fileTypeFromFile(path, options) {
|
|
109
|
-
return (new FileTypeParser(options)).fromFile(path, options);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export async function fileTypeFromStream(stream, options) {
|
|
113
|
-
return (new FileTypeParser(options)).fromStream(stream);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export async function fileTypeStream(readableStream, options = {}) {
|
|
117
|
-
return new FileTypeParser(options).toDetectionStream(readableStream, options);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export {
|
|
121
|
-
fileTypeFromTokenizer,
|
|
122
|
-
fileTypeFromBuffer,
|
|
123
|
-
fileTypeFromBlob,
|
|
124
|
-
supportedMimeTypes,
|
|
125
|
-
supportedExtensions,
|
|
126
|
-
} from './core.js';
|