file-type 18.5.0 → 18.7.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/core.d.ts +100 -7
- package/core.js +110 -61
- package/index.js +4 -3
- package/package.json +5 -2
- package/readme.md +78 -19
- package/supported.js +4 -0
package/core.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ export type FileExtension =
|
|
|
50
50
|
| 'epub'
|
|
51
51
|
| 'mobi'
|
|
52
52
|
| 'elf'
|
|
53
|
+
| 'macho'
|
|
53
54
|
| 'exe'
|
|
54
55
|
| 'swf'
|
|
55
56
|
| 'rtf'
|
|
@@ -152,6 +153,7 @@ export type FileExtension =
|
|
|
152
153
|
| 'ace'
|
|
153
154
|
| 'avro'
|
|
154
155
|
| 'icc'
|
|
156
|
+
| 'fbx'
|
|
155
157
|
; // eslint-disable-line semi-style
|
|
156
158
|
|
|
157
159
|
export type MimeType =
|
|
@@ -209,6 +211,7 @@ export type MimeType =
|
|
|
209
211
|
| 'audio/amr'
|
|
210
212
|
| 'application/pdf'
|
|
211
213
|
| 'application/x-elf'
|
|
214
|
+
| 'application/x-mach-binary'
|
|
212
215
|
| 'application/x-msdownload'
|
|
213
216
|
| 'application/x-shockwave-flash'
|
|
214
217
|
| 'application/rtf'
|
|
@@ -300,6 +303,7 @@ export type MimeType =
|
|
|
300
303
|
| 'application/x-ace-compressed'
|
|
301
304
|
| 'application/avro'
|
|
302
305
|
| 'application/vnd.iccprofile'
|
|
306
|
+
| 'application/x.autodesk.fbx'
|
|
303
307
|
; // eslint-disable-line semi-style
|
|
304
308
|
|
|
305
309
|
export type FileTypeResult = {
|
|
@@ -325,8 +329,8 @@ The file type is detected by checking the [magic number](https://en.wikipedia.or
|
|
|
325
329
|
|
|
326
330
|
If file access is available, it is recommended to use `.fromFile()` instead.
|
|
327
331
|
|
|
328
|
-
@param buffer - An Uint8Array or Buffer representing file data. It works best if the buffer contains the entire file
|
|
329
|
-
@returns The detected file type
|
|
332
|
+
@param buffer - An Uint8Array or Buffer representing file data. It works best if the buffer contains the entire file. It may work with a smaller portion as well.
|
|
333
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
330
334
|
*/
|
|
331
335
|
export function fileTypeFromBuffer(buffer: Uint8Array | ArrayBuffer): Promise<FileTypeResult | undefined>;
|
|
332
336
|
|
|
@@ -336,7 +340,7 @@ Detect the file type of a Node.js [readable stream](https://nodejs.org/api/strea
|
|
|
336
340
|
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.
|
|
337
341
|
|
|
338
342
|
@param stream - A readable stream representing file data.
|
|
339
|
-
@returns The detected file type
|
|
343
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
340
344
|
*/
|
|
341
345
|
export function fileTypeFromStream(stream: ReadableStream): Promise<FileTypeResult | undefined>;
|
|
342
346
|
|
|
@@ -348,7 +352,7 @@ This method is used internally, but can also be used for a special "tokenizer" r
|
|
|
348
352
|
A tokenizer propagates the internal read functions, allowing alternative transport mechanisms, to access files, to be implemented and used.
|
|
349
353
|
|
|
350
354
|
@param tokenizer - File source implementing the tokenizer interface.
|
|
351
|
-
@returns The detected file type
|
|
355
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
352
356
|
|
|
353
357
|
An example is [`@tokenizer/http`](https://github.com/Borewit/tokenizer-http), which requests data using [HTTP-range-requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests). A difference with a conventional stream and the [*tokenizer*](https://github.com/Borewit/strtok3#tokenizer), is that it is able to *ignore* (seek, fast-forward) in the stream. For example, you may only need and read the first 6 bytes, and the last 128 bytes, which may be an advantage in case reading the entire file would take longer.
|
|
354
358
|
|
|
@@ -419,19 +423,108 @@ if (stream2.fileType?.mime === 'image/jpeg') {
|
|
|
419
423
|
export function fileTypeStream(readableStream: ReadableStream, options?: StreamOptions): Promise<ReadableStreamWithFileType>;
|
|
420
424
|
|
|
421
425
|
/**
|
|
422
|
-
Detect the file type of a [`Blob`](https://nodejs.org/api/buffer.html#class-blob).
|
|
426
|
+
Detect the file type of a [`Blob`](https://nodejs.org/api/buffer.html#class-blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).
|
|
427
|
+
|
|
428
|
+
@param blob - The [`Blob`](https://nodejs.org/api/buffer.html#class-blob) used for file detection.
|
|
429
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
423
430
|
|
|
424
431
|
@example
|
|
425
432
|
```
|
|
426
433
|
import {fileTypeFromBlob} from 'file-type';
|
|
427
434
|
|
|
428
435
|
const blob = new Blob(['<?xml version="1.0" encoding="ISO-8859-1" ?>'], {
|
|
429
|
-
type: 'plain
|
|
436
|
+
type: 'text/plain',
|
|
430
437
|
endings: 'native'
|
|
431
438
|
});
|
|
432
439
|
|
|
433
440
|
console.log(await fileTypeFromBlob(blob));
|
|
434
|
-
//=> {ext: 'txt', mime: 'plain
|
|
441
|
+
//=> {ext: 'txt', mime: 'text/plain'}
|
|
435
442
|
```
|
|
436
443
|
*/
|
|
437
444
|
export declare function fileTypeFromBlob(blob: Blob): Promise<FileTypeResult | undefined>;
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
Function that allows specifying custom detection mechanisms.
|
|
448
|
+
|
|
449
|
+
An iterable of detectors can be provided via the `fileTypeOptions` argument for the {@link FileTypeParser.constructor}.
|
|
450
|
+
|
|
451
|
+
The detectors are called before the default detections in the provided order.
|
|
452
|
+
|
|
453
|
+
Custom detectors can be used to add new `FileTypeResults` or to modify return behavior of existing `FileTypeResult` detections.
|
|
454
|
+
|
|
455
|
+
If the detector returns `undefined`, there are 2 possible scenarios:
|
|
456
|
+
|
|
457
|
+
1. The detector has not read from the tokenizer, it will be proceeded with the next available detector.
|
|
458
|
+
2. The detector has read from the tokenizer (`tokenizer.position` has been increased).
|
|
459
|
+
In that case no further detectors will be executed and the final conclusion is that file-type returns undefined.
|
|
460
|
+
Note that this an exceptional scenario, as the detector takes the opportunity from any other detector to determine the file type.
|
|
461
|
+
|
|
462
|
+
Example detector array which can be extended and provided via the fileTypeOptions argument:
|
|
463
|
+
|
|
464
|
+
```
|
|
465
|
+
import {FileTypeParser} from 'file-type';
|
|
466
|
+
|
|
467
|
+
const customDetectors = [
|
|
468
|
+
async tokenizer => {
|
|
469
|
+
const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // 'UNICORN' as decimal string
|
|
470
|
+
|
|
471
|
+
const buffer = Buffer.alloc(7);
|
|
472
|
+
await tokenizer.peekBuffer(buffer, {length: unicornHeader.length, mayBeLess: true});
|
|
473
|
+
if (unicornHeader.every((value, index) => value === buffer[index])) {
|
|
474
|
+
return {ext: 'unicorn', mime: 'application/unicorn'};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return undefined;
|
|
478
|
+
},
|
|
479
|
+
];
|
|
480
|
+
|
|
481
|
+
const buffer = Buffer.from('UNICORN');
|
|
482
|
+
const parser = new FileTypeParser({customDetectors});
|
|
483
|
+
const fileType = await parser.fromBuffer(buffer);
|
|
484
|
+
console.log(fileType);
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
@param tokenizer - The [tokenizer](https://github.com/Borewit/strtok3#tokenizer) used to read the file content from.
|
|
488
|
+
@param fileType - The file type detected by the standard detections or a previous custom detection, or `undefined`` if no matching file type could be found.
|
|
489
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
490
|
+
*/
|
|
491
|
+
export type Detector = (tokenizer: ITokenizer, fileType?: FileTypeResult) => Promise<FileTypeResult | undefined>;
|
|
492
|
+
|
|
493
|
+
export type FileTypeOptions = {
|
|
494
|
+
customDetectors?: Iterable<Detector>;
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
export declare class TokenizerPositionError extends Error {
|
|
498
|
+
constructor(message?: string);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
export declare class FileTypeParser {
|
|
502
|
+
detectors: Iterable<Detector>;
|
|
503
|
+
|
|
504
|
+
constructor(options?: {customDetectors?: Iterable<Detector>});
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
Works the same way as {@link fileTypeFromBuffer}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
508
|
+
*/
|
|
509
|
+
fromBuffer(buffer: Uint8Array | ArrayBuffer): Promise<FileTypeResult | undefined>;
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
Works the same way as {@link fileTypeFromStream}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
513
|
+
*/
|
|
514
|
+
fromStream(stream: ReadableStream): Promise<FileTypeResult | undefined>;
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
Works the same way as {@link fileTypeFromTokenizer}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
518
|
+
*/
|
|
519
|
+
fromTokenizer(tokenizer: ITokenizer): Promise<FileTypeResult | undefined>;
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
Works the same way as {@link fileTypeFromBlob}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
523
|
+
*/
|
|
524
|
+
fromBlob(blob: Blob): Promise<FileTypeResult | undefined>;
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
Works the same way as {@link fileTypeStream}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
528
|
+
*/
|
|
529
|
+
toDetectionStream(readableStream: ReadableStream, options?: StreamOptions): Promise<FileTypeResult | undefined>;
|
|
530
|
+
}
|
package/core.js
CHANGED
|
@@ -11,31 +11,15 @@ import {extensions, mimeTypes} from './supported.js';
|
|
|
11
11
|
const minimumBytes = 4100; // A fair amount of file-types are detectable within this range.
|
|
12
12
|
|
|
13
13
|
export async function fileTypeFromStream(stream) {
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
return await fileTypeFromTokenizer(tokenizer);
|
|
17
|
-
} finally {
|
|
18
|
-
await tokenizer.close();
|
|
19
|
-
}
|
|
14
|
+
return new FileTypeParser().fromStream(stream);
|
|
20
15
|
}
|
|
21
16
|
|
|
22
17
|
export async function fileTypeFromBuffer(input) {
|
|
23
|
-
|
|
24
|
-
throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
28
|
-
|
|
29
|
-
if (!(buffer?.length > 1)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return fileTypeFromTokenizer(strtok3.fromBuffer(buffer));
|
|
18
|
+
return new FileTypeParser().fromBuffer(input);
|
|
34
19
|
}
|
|
35
20
|
|
|
36
21
|
export async function fileTypeFromBlob(blob) {
|
|
37
|
-
|
|
38
|
-
return fileTypeFromBuffer(new Uint8Array(buffer));
|
|
22
|
+
return new FileTypeParser().fromBlob(blob);
|
|
39
23
|
}
|
|
40
24
|
|
|
41
25
|
function _check(buffer, headers, options) {
|
|
@@ -60,16 +44,98 @@ function _check(buffer, headers, options) {
|
|
|
60
44
|
}
|
|
61
45
|
|
|
62
46
|
export async function fileTypeFromTokenizer(tokenizer) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
return new FileTypeParser().fromTokenizer(tokenizer);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class FileTypeParser {
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.detectors = options?.customDetectors;
|
|
53
|
+
|
|
54
|
+
this.fromTokenizer = this.fromTokenizer.bind(this);
|
|
55
|
+
this.fromBuffer = this.fromBuffer.bind(this);
|
|
56
|
+
this.parse = this.parse.bind(this);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async fromTokenizer(tokenizer) {
|
|
60
|
+
const initialPosition = tokenizer.position;
|
|
61
|
+
|
|
62
|
+
for (const detector of this.detectors || []) {
|
|
63
|
+
const fileType = await detector(tokenizer);
|
|
64
|
+
if (fileType) {
|
|
65
|
+
return fileType;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (initialPosition !== tokenizer.position) {
|
|
69
|
+
return undefined; // Cannot proceed scanning of the tokenizer is at an arbitrary position
|
|
70
|
+
}
|
|
68
71
|
}
|
|
72
|
+
|
|
73
|
+
return this.parse(tokenizer);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async fromBuffer(input) {
|
|
77
|
+
if (!(input instanceof Uint8Array || input instanceof ArrayBuffer)) {
|
|
78
|
+
throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
82
|
+
|
|
83
|
+
if (!(buffer?.length > 1)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return this.fromTokenizer(strtok3.fromBuffer(buffer));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async fromBlob(blob) {
|
|
91
|
+
const buffer = await blob.arrayBuffer();
|
|
92
|
+
return this.fromBuffer(new Uint8Array(buffer));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async fromStream(stream) {
|
|
96
|
+
const tokenizer = await strtok3.fromStream(stream);
|
|
97
|
+
try {
|
|
98
|
+
return await this.fromTokenizer(tokenizer);
|
|
99
|
+
} finally {
|
|
100
|
+
await tokenizer.close();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async toDetectionStream(readableStream, options = {}) {
|
|
105
|
+
const {default: stream} = await import('node:stream');
|
|
106
|
+
const {sampleSize = minimumBytes} = options;
|
|
107
|
+
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
readableStream.on('error', reject);
|
|
110
|
+
|
|
111
|
+
readableStream.once('readable', () => {
|
|
112
|
+
(async () => {
|
|
113
|
+
try {
|
|
114
|
+
// Set up output stream
|
|
115
|
+
const pass = new stream.PassThrough();
|
|
116
|
+
const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
|
|
117
|
+
|
|
118
|
+
// Read the input stream and detect the filetype
|
|
119
|
+
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? Buffer.alloc(0);
|
|
120
|
+
try {
|
|
121
|
+
pass.fileType = await this.fromBuffer(chunk);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error instanceof strtok3.EndOfStreamError) {
|
|
124
|
+
pass.fileType = undefined;
|
|
125
|
+
} else {
|
|
126
|
+
reject(error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
resolve(outputStream);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
reject(error);
|
|
133
|
+
}
|
|
134
|
+
})();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
69
137
|
}
|
|
70
|
-
}
|
|
71
138
|
|
|
72
|
-
class FileTypeParser {
|
|
73
139
|
check(header, options) {
|
|
74
140
|
return _check(this.buffer, header, options);
|
|
75
141
|
}
|
|
@@ -211,7 +277,7 @@ class FileTypeParser {
|
|
|
211
277
|
}
|
|
212
278
|
|
|
213
279
|
await tokenizer.ignore(id3HeaderLength);
|
|
214
|
-
return
|
|
280
|
+
return this.fromTokenizer(tokenizer); // Skip ID3 header, recursion
|
|
215
281
|
}
|
|
216
282
|
|
|
217
283
|
// Musepack, SV7
|
|
@@ -694,7 +760,7 @@ class FileTypeParser {
|
|
|
694
760
|
};
|
|
695
761
|
}
|
|
696
762
|
|
|
697
|
-
// https://github.com/
|
|
763
|
+
// https://github.com/file/file/blob/master/magic/Magdir/matroska
|
|
698
764
|
if (this.check([0x1A, 0x45, 0xDF, 0xA3])) { // Root element: EBML
|
|
699
765
|
async function readField() {
|
|
700
766
|
const msb = await tokenizer.peekNumber(Token.UINT8);
|
|
@@ -855,6 +921,13 @@ class FileTypeParser {
|
|
|
855
921
|
};
|
|
856
922
|
}
|
|
857
923
|
|
|
924
|
+
if (this.check([0xCF, 0xFA, 0xED, 0xFE])) {
|
|
925
|
+
return {
|
|
926
|
+
ext: 'macho',
|
|
927
|
+
mime: 'application/x-mach-binary',
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
|
|
858
931
|
// -- 5-byte signatures --
|
|
859
932
|
|
|
860
933
|
if (this.check([0x4F, 0x54, 0x54, 0x4F, 0x00])) {
|
|
@@ -1433,6 +1506,13 @@ class FileTypeParser {
|
|
|
1433
1506
|
};
|
|
1434
1507
|
}
|
|
1435
1508
|
|
|
1509
|
+
if (this.checkString('Kaydara FBX Binary \u0000')) {
|
|
1510
|
+
return {
|
|
1511
|
+
ext: 'fbx',
|
|
1512
|
+
mime: 'application/x.autodesk.fbx', // Invented by us
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1436
1516
|
if (
|
|
1437
1517
|
this.check([0x4C, 0x50], {offset: 34})
|
|
1438
1518
|
&& (
|
|
@@ -1602,39 +1682,8 @@ class FileTypeParser {
|
|
|
1602
1682
|
}
|
|
1603
1683
|
}
|
|
1604
1684
|
|
|
1605
|
-
export async function fileTypeStream(readableStream,
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
return new Promise((resolve, reject) => {
|
|
1609
|
-
readableStream.on('error', reject);
|
|
1610
|
-
|
|
1611
|
-
readableStream.once('readable', () => {
|
|
1612
|
-
(async () => {
|
|
1613
|
-
try {
|
|
1614
|
-
// Set up output stream
|
|
1615
|
-
const pass = new stream.PassThrough();
|
|
1616
|
-
const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
|
|
1617
|
-
|
|
1618
|
-
// Read the input stream and detect the filetype
|
|
1619
|
-
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? Buffer.alloc(0);
|
|
1620
|
-
try {
|
|
1621
|
-
const fileType = await fileTypeFromBuffer(chunk);
|
|
1622
|
-
pass.fileType = fileType;
|
|
1623
|
-
} catch (error) {
|
|
1624
|
-
if (error instanceof strtok3.EndOfStreamError) {
|
|
1625
|
-
pass.fileType = undefined;
|
|
1626
|
-
} else {
|
|
1627
|
-
reject(error);
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
resolve(outputStream);
|
|
1632
|
-
} catch (error) {
|
|
1633
|
-
reject(error);
|
|
1634
|
-
}
|
|
1635
|
-
})();
|
|
1636
|
-
});
|
|
1637
|
-
});
|
|
1685
|
+
export async function fileTypeStream(readableStream, options = {}) {
|
|
1686
|
+
return new FileTypeParser().toDetectionStream(readableStream, options);
|
|
1638
1687
|
}
|
|
1639
1688
|
|
|
1640
1689
|
export const supportedExtensions = new Set(extensions);
|
package/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as strtok3 from 'strtok3';
|
|
2
|
-
import {
|
|
2
|
+
import {FileTypeParser} from './core.js';
|
|
3
3
|
|
|
4
|
-
export async function fileTypeFromFile(path) {
|
|
4
|
+
export async function fileTypeFromFile(path, fileTypeOptions) {
|
|
5
5
|
const tokenizer = await strtok3.fromFile(path);
|
|
6
6
|
try {
|
|
7
|
-
|
|
7
|
+
const parser = new FileTypeParser(fileTypeOptions);
|
|
8
|
+
return await parser.fromTokenizer(tokenizer);
|
|
8
9
|
} finally {
|
|
9
10
|
await tokenizer.close();
|
|
10
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-type",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.7.0",
|
|
4
4
|
"description": "Detect the file type of a Buffer/Uint8Array/ArrayBuffer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/file-type",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"./core": "./core.js"
|
|
20
20
|
},
|
|
21
|
+
"sideEffects": false,
|
|
21
22
|
"engines": {
|
|
22
23
|
"node": ">=14.16"
|
|
23
24
|
},
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"is",
|
|
53
54
|
"exif",
|
|
54
55
|
"elf",
|
|
56
|
+
"macho",
|
|
55
57
|
"exe",
|
|
56
58
|
"binary",
|
|
57
59
|
"buffer",
|
|
@@ -204,7 +206,8 @@
|
|
|
204
206
|
"cpio",
|
|
205
207
|
"ace",
|
|
206
208
|
"avro",
|
|
207
|
-
"icc"
|
|
209
|
+
"icc",
|
|
210
|
+
"fbx"
|
|
208
211
|
],
|
|
209
212
|
"dependencies": {
|
|
210
213
|
"readable-web-to-node-stream": "^3.0.2",
|
package/readme.md
CHANGED
|
@@ -113,7 +113,7 @@ The file type is detected by checking the [magic number](https://en.wikipedia.or
|
|
|
113
113
|
|
|
114
114
|
If file access is available, it is recommended to use `fileTypeFromFile()` instead.
|
|
115
115
|
|
|
116
|
-
Returns a `Promise` for an object with the detected file type
|
|
116
|
+
Returns a `Promise` for an object with the detected file type:
|
|
117
117
|
|
|
118
118
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
119
119
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -124,7 +124,7 @@ Or `undefined` when there is no match.
|
|
|
124
124
|
|
|
125
125
|
Type: `Buffer | Uint8Array | ArrayBuffer`
|
|
126
126
|
|
|
127
|
-
A buffer representing file data. It works best if the buffer contains the entire file
|
|
127
|
+
A buffer representing file data. It works best if the buffer contains the entire file. It may work with a smaller portion as well.
|
|
128
128
|
|
|
129
129
|
### fileTypeFromFile(filePath)
|
|
130
130
|
|
|
@@ -132,7 +132,7 @@ Detect the file type of a file path.
|
|
|
132
132
|
|
|
133
133
|
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.
|
|
134
134
|
|
|
135
|
-
Returns a `Promise` for an object with the detected file type
|
|
135
|
+
Returns a `Promise` for an object with the detected file type:
|
|
136
136
|
|
|
137
137
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
138
138
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -151,7 +151,7 @@ Detect the file type of a Node.js [readable stream](https://nodejs.org/api/strea
|
|
|
151
151
|
|
|
152
152
|
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.
|
|
153
153
|
|
|
154
|
-
Returns a `Promise` for an object with the detected file type
|
|
154
|
+
Returns a `Promise` for an object with the detected file type:
|
|
155
155
|
|
|
156
156
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
157
157
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -170,7 +170,7 @@ Detect the file type of a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/
|
|
|
170
170
|
|
|
171
171
|
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.
|
|
172
172
|
|
|
173
|
-
Returns a `Promise` for an object with the detected file type
|
|
173
|
+
Returns a `Promise` for an object with the detected file type:
|
|
174
174
|
|
|
175
175
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
176
176
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -181,14 +181,18 @@ Or `undefined` when there is no match.
|
|
|
181
181
|
import {fileTypeFromBlob} from 'file-type';
|
|
182
182
|
|
|
183
183
|
const blob = new Blob(['<?xml version="1.0" encoding="ISO-8859-1" ?>'], {
|
|
184
|
-
type: 'plain
|
|
184
|
+
type: 'text/plain',
|
|
185
185
|
endings: 'native'
|
|
186
186
|
});
|
|
187
187
|
|
|
188
188
|
console.log(await fileTypeFromBlob(blob));
|
|
189
|
-
//=> {ext: 'txt', mime: 'plain
|
|
189
|
+
//=> {ext: 'txt', mime: 'text/plain'}
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
+
#### blob
|
|
193
|
+
|
|
194
|
+
Type: [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
|
195
|
+
|
|
192
196
|
### fileTypeFromTokenizer(tokenizer)
|
|
193
197
|
|
|
194
198
|
Detect the file type from an `ITokenizer` source.
|
|
@@ -197,7 +201,7 @@ This method is used internally, but can also be used for a special "tokenizer" r
|
|
|
197
201
|
|
|
198
202
|
A tokenizer propagates the internal read functions, allowing alternative transport mechanisms, to access files, to be implemented and used.
|
|
199
203
|
|
|
200
|
-
Returns a `Promise` for an object with the detected file type
|
|
204
|
+
Returns a `Promise` for an object with the detected file type:
|
|
201
205
|
|
|
202
206
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
203
207
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -305,6 +309,49 @@ Returns a `Set<string>` of supported file extensions.
|
|
|
305
309
|
|
|
306
310
|
Returns a `Set<string>` of supported MIME types.
|
|
307
311
|
|
|
312
|
+
## Custom detectors
|
|
313
|
+
|
|
314
|
+
A custom detector is a function that allows specifying custom detection mechanisms.
|
|
315
|
+
|
|
316
|
+
An iterable of detectors can be provided via the `fileTypeOptions` argument for the `FileTypeParser` constructor.
|
|
317
|
+
|
|
318
|
+
The detectors are called before the default detections in the provided order.
|
|
319
|
+
|
|
320
|
+
Custom detectors can be used to add new `FileTypeResults` or to modify return behaviour of existing `FileTypeResult` detections.
|
|
321
|
+
|
|
322
|
+
If the detector returns `undefined`, there are 2 possible scenarios:
|
|
323
|
+
|
|
324
|
+
1. The detector has not read from the tokenizer, it will be proceeded with the next available detector.
|
|
325
|
+
2. The detector has read from the tokenizer (`tokenizer.position` has been increased).
|
|
326
|
+
In that case no further detectors will be executed and the final conclusion is that file-type returns undefined.
|
|
327
|
+
Note that this an exceptional scenario, as the detector takes the opportunity from any other detector to determine the file type.
|
|
328
|
+
|
|
329
|
+
Example detector array which can be extended and provided to each public method via the `fileTypeOptions` argument:
|
|
330
|
+
|
|
331
|
+
```js
|
|
332
|
+
import {FileTypeParser} from 'file-type';
|
|
333
|
+
|
|
334
|
+
const customDetectors = [
|
|
335
|
+
async tokenizer => {
|
|
336
|
+
const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // 'UNICORN' as decimal string
|
|
337
|
+
|
|
338
|
+
const buffer = Buffer.alloc(7);
|
|
339
|
+
await tokenizer.peekBuffer(buffer, {length: unicornHeader.length, mayBeLess: true});
|
|
340
|
+
|
|
341
|
+
if (unicornHeader.every((value, index) => value === buffer[index])) {
|
|
342
|
+
return {ext: 'unicorn', mime: 'application/unicorn'};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return undefined;
|
|
346
|
+
},
|
|
347
|
+
];
|
|
348
|
+
|
|
349
|
+
const buffer = Buffer.from('UNICORN');
|
|
350
|
+
const parser = new FileTypeParser({customDetectors});
|
|
351
|
+
const fileType = await parser.fromBuffer(buffer);
|
|
352
|
+
console.log(fileType);
|
|
353
|
+
```
|
|
354
|
+
|
|
308
355
|
## Supported file types
|
|
309
356
|
|
|
310
357
|
- [`3g2`](https://en.wikipedia.org/wiki/3GP_and_3G2#3G2) - Multimedia container format defined by the 3GPP2 for 3G CDMA2000 multimedia services
|
|
@@ -335,7 +382,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
335
382
|
- [`bpg`](https://bellard.org/bpg/) - Better Portable Graphics file
|
|
336
383
|
- [`bz2`](https://en.wikipedia.org/wiki/Bzip2) - Archive file
|
|
337
384
|
- [`cab`](https://en.wikipedia.org/wiki/Cabinet_(file_format)) - Cabinet file
|
|
338
|
-
- [`cfb`](https://en.wikipedia.org/wiki/Compound_File_Binary_Format) -
|
|
385
|
+
- [`cfb`](https://en.wikipedia.org/wiki/Compound_File_Binary_Format) - Compound File Binary Format
|
|
339
386
|
- [`chm`](https://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help) - Microsoft Compiled HTML Help
|
|
340
387
|
- [`class`](https://en.wikipedia.org/wiki/Java_class_file) - Java class file
|
|
341
388
|
- [`cpio`](https://en.wikipedia.org/wiki/Cpio) - Cpio archive
|
|
@@ -347,7 +394,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
347
394
|
- [`deb`](https://en.wikipedia.org/wiki/Deb_(file_format)) - Debian package
|
|
348
395
|
- [`dmg`](https://en.wikipedia.org/wiki/Apple_Disk_Image) - Apple Disk Image
|
|
349
396
|
- [`dng`](https://en.wikipedia.org/wiki/Digital_Negative) - Adobe Digital Negative image file
|
|
350
|
-
- [`docx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Word
|
|
397
|
+
- [`docx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Word document
|
|
351
398
|
- [`dsf`](https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf) - Sony DSD Stream File (DSF)
|
|
352
399
|
- [`dwg`](https://en.wikipedia.org/wiki/.dwg) - Autodesk CAD file
|
|
353
400
|
- [`elf`](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) - Unix Executable and Linkable Format
|
|
@@ -359,6 +406,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
359
406
|
- [`f4b`](https://en.wikipedia.org/wiki/Flash_Video) - Audiobook and podcast ISO base media file format used by Adobe Flash Player
|
|
360
407
|
- [`f4p`](https://en.wikipedia.org/wiki/Flash_Video) - ISO base media file format protected by Adobe Access DRM used by Adobe Flash Player
|
|
361
408
|
- [`f4v`](https://en.wikipedia.org/wiki/Flash_Video) - ISO base media file format used by Adobe Flash Player
|
|
409
|
+
- [`fbx`](https://en.wikipedia.org/wiki/FBX) - Filmbox is a proprietary file format used to provide interoperability between digital content creation apps.
|
|
362
410
|
- [`flac`](https://en.wikipedia.org/wiki/FLAC) - Free Lossless Audio Codec
|
|
363
411
|
- [`flif`](https://en.wikipedia.org/wiki/Free_Lossless_Image_Format) - Free Lossless Image Format
|
|
364
412
|
- [`flv`](https://en.wikipedia.org/wiki/Flash_Video) - Flash video
|
|
@@ -382,12 +430,13 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
382
430
|
- [`jxr`](https://en.wikipedia.org/wiki/JPEG_XR) - Joint Photographic Experts Group extended range
|
|
383
431
|
- [`ktx`](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/) - OpenGL and OpenGL ES textures
|
|
384
432
|
- [`lnk`](https://en.wikipedia.org/wiki/Shortcut_%28computing%29#Microsoft_Windows) - Microsoft Windows file shortcut
|
|
385
|
-
- [`lz`](https://en.wikipedia.org/wiki/Lzip) -
|
|
433
|
+
- [`lz`](https://en.wikipedia.org/wiki/Lzip) - Archive file
|
|
386
434
|
- [`lzh`](https://en.wikipedia.org/wiki/LHA_(file_format)) - LZH archive
|
|
387
435
|
- [`m4a`](https://en.wikipedia.org/wiki/M4A) - Audio-only MPEG-4 files
|
|
388
436
|
- [`m4b`](https://en.wikipedia.org/wiki/M4B) - Audiobook and podcast MPEG-4 files, which also contain metadata including chapter markers, images, and hyperlinks
|
|
389
437
|
- [`m4p`](https://en.wikipedia.org/wiki/MPEG-4_Part_14#Filename_extensions) - MPEG-4 files with audio streams encrypted by FairPlay Digital Rights Management as were sold through the iTunes Store
|
|
390
438
|
- [`m4v`](https://en.wikipedia.org/wiki/M4V) - Video container format developed by Apple, which is very similar to the MP4 format
|
|
439
|
+
- [`macho`](https://en.wikipedia.org/wiki/Mach-O) - Mach-O binary format
|
|
391
440
|
- [`mid`](https://en.wikipedia.org/wiki/MIDI) - Musical Instrument Digital Interface file
|
|
392
441
|
- [`mie`](https://en.wikipedia.org/wiki/Sidecar_file) - Dedicated meta information format which supports storage of binary as well as textual meta information
|
|
393
442
|
- [`mj2`](https://en.wikipedia.org/wiki/Motion_JPEG_2000) - Motion JPEG 2000
|
|
@@ -420,7 +469,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
420
469
|
- [`pdf`](https://en.wikipedia.org/wiki/Portable_Document_Format) - Portable Document Format
|
|
421
470
|
- [`pgp`](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) - Pretty Good Privacy
|
|
422
471
|
- [`png`](https://en.wikipedia.org/wiki/Portable_Network_Graphics) - Portable Network Graphics
|
|
423
|
-
- [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Powerpoint
|
|
472
|
+
- [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Powerpoint document
|
|
424
473
|
- [`ps`](https://en.wikipedia.org/wiki/Postscript) - Postscript
|
|
425
474
|
- [`psd`](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) - Adobe Photoshop document
|
|
426
475
|
- [`pst`](https://en.wikipedia.org/wiki/Personal_Storage_Table) - Personal Storage Table file
|
|
@@ -450,7 +499,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
450
499
|
- [`woff2`](https://en.wikipedia.org/wiki/Web_Open_Font_Format) - Web Open Font Format
|
|
451
500
|
- [`wv`](https://en.wikipedia.org/wiki/WavPack) - WavPack
|
|
452
501
|
- [`xcf`](https://en.wikipedia.org/wiki/XCF_(file_format)) - eXperimental Computing Facility
|
|
453
|
-
- [`xlsx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Excel
|
|
502
|
+
- [`xlsx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Excel document
|
|
454
503
|
- [`xm`](https://wiki.openmpt.org/Manual:_Module_formats#The_FastTracker_2_format_.28.xm.29) - Audio module format: FastTracker 2
|
|
455
504
|
- [`xml`](https://en.wikipedia.org/wiki/XML) - eXtensible Markup Language
|
|
456
505
|
- [`xpi`](https://en.wikipedia.org/wiki/XPInstall) - XPInstall file
|
|
@@ -458,7 +507,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
458
507
|
- [`zip`](https://en.wikipedia.org/wiki/Zip_(file_format)) - Archive file
|
|
459
508
|
- [`zst`](https://en.wikipedia.org/wiki/Zstandard) - Archive file
|
|
460
509
|
|
|
461
|
-
*Pull requests are welcome for additional commonly used file types.*
|
|
510
|
+
*[Pull requests](.github/pull_request_template.md) are welcome for additional commonly used file types.*
|
|
462
511
|
|
|
463
512
|
The following file types will not be accepted:
|
|
464
513
|
- [MS-CFB: Microsoft Compound File Binary File Format based formats](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/53989ce4-7b05-4f8d-829b-d08d6148375b), too old and difficult to parse:
|
|
@@ -469,16 +518,26 @@ The following file types will not be accepted:
|
|
|
469
518
|
- `.csv` - [Reason.](https://github.com/sindresorhus/file-type/issues/264#issuecomment-568439196)
|
|
470
519
|
- `.svg` - Detecting it requires a full-blown parser. Check out [`is-svg`](https://github.com/sindresorhus/is-svg) for something that mostly works.
|
|
471
520
|
|
|
521
|
+
#### tokenizer
|
|
522
|
+
|
|
523
|
+
Type: [`ITokenizer`](https://github.com/Borewit/strtok3#tokenizer)
|
|
524
|
+
|
|
525
|
+
Usable as source of the examined file.
|
|
526
|
+
|
|
527
|
+
#### fileType
|
|
528
|
+
|
|
529
|
+
Type: `FileTypeResult`
|
|
530
|
+
|
|
531
|
+
An object having an `ext` (extension) and `mime` (mime type) property.
|
|
532
|
+
|
|
533
|
+
Detected by the standard detections or a previous custom detection. Undefined if no matching fileTypeResult could be found.
|
|
534
|
+
|
|
472
535
|
## Related
|
|
473
536
|
|
|
474
537
|
- [file-type-cli](https://github.com/sindresorhus/file-type-cli) - CLI for this module
|
|
538
|
+
- [image-dimensions](https://github.com/sindresorhus/image-dimensions) - Get the dimensions of an image
|
|
475
539
|
|
|
476
540
|
## Maintainers
|
|
477
541
|
|
|
478
542
|
- [Sindre Sorhus](https://github.com/sindresorhus)
|
|
479
543
|
- [Borewit](https://github.com/Borewit)
|
|
480
|
-
|
|
481
|
-
**Former**
|
|
482
|
-
|
|
483
|
-
- [Mikael Finstad](https://github.com/mifi)
|
|
484
|
-
- [Ben Brook](https://github.com/bencmbrook)
|
package/supported.js
CHANGED
|
@@ -48,6 +48,7 @@ export const extensions = [
|
|
|
48
48
|
'pdf',
|
|
49
49
|
'epub',
|
|
50
50
|
'elf',
|
|
51
|
+
'macho',
|
|
51
52
|
'exe',
|
|
52
53
|
'swf',
|
|
53
54
|
'rtf',
|
|
@@ -149,6 +150,7 @@ export const extensions = [
|
|
|
149
150
|
'ace',
|
|
150
151
|
'avro',
|
|
151
152
|
'icc',
|
|
153
|
+
'fbx',
|
|
152
154
|
];
|
|
153
155
|
|
|
154
156
|
export const mimeTypes = [
|
|
@@ -206,6 +208,7 @@ export const mimeTypes = [
|
|
|
206
208
|
'audio/amr',
|
|
207
209
|
'application/pdf',
|
|
208
210
|
'application/x-elf',
|
|
211
|
+
'application/x-mach-binary',
|
|
209
212
|
'application/x-msdownload',
|
|
210
213
|
'application/x-shockwave-flash',
|
|
211
214
|
'application/rtf',
|
|
@@ -297,4 +300,5 @@ export const mimeTypes = [
|
|
|
297
300
|
'application/x-ace-compressed',
|
|
298
301
|
'application/avro',
|
|
299
302
|
'application/vnd.iccprofile',
|
|
303
|
+
'application/x.autodesk.fbx', // Invented by us
|
|
300
304
|
];
|