Skip to content

Commit 30b1ffc

Browse files
authored
Merge pull request #1158 from constructive-io/fix/heic-detection
fix(mime-bytes): detect HEIC/HEIF instead of misidentifying as MP4
2 parents 42ff6bf + fb9a3be commit 30b1ffc

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

uploads/mime-bytes/__tests__/file-type-detector.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ describe('FileTypeDetector', () => {
6565
});
6666

6767
it('should detect MP4 files with offset', async () => {
68+
// ftyp + "isom" brand = generic MP4
6869
const mp4Buffer = Buffer.from([
6970
0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70,
7071
0x69, 0x73, 0x6F, 0x6D, 0x00, 0x00, 0x02, 0x00
@@ -77,6 +78,34 @@ describe('FileTypeDetector', () => {
7778
expect(result?.extensions).toContain('mp4');
7879
});
7980

81+
it('should detect HEIC files (not misidentify as MP4)', async () => {
82+
// ftyp + "heic" brand = HEIC image
83+
const heicBuffer = Buffer.from([
84+
0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70,
85+
0x68, 0x65, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00
86+
]);
87+
88+
const result = await detector.detectFromBuffer(heicBuffer);
89+
expect(result).toBeDefined();
90+
expect(result?.name).toBe('heic');
91+
expect(result?.mimeType).toBe('image/heic');
92+
expect(result?.extensions).toContain('heic');
93+
});
94+
95+
it('should detect HEIF files (not misidentify as MP4)', async () => {
96+
// ftyp + "mif1" brand = HEIF image
97+
const heifBuffer = Buffer.from([
98+
0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70,
99+
0x6D, 0x69, 0x66, 0x31, 0x00, 0x00, 0x00, 0x00
100+
]);
101+
102+
const result = await detector.detectFromBuffer(heifBuffer);
103+
expect(result).toBeDefined();
104+
expect(result?.name).toBe('heif');
105+
expect(result?.mimeType).toBe('image/heif');
106+
expect(result?.extensions).toContain('heif');
107+
});
108+
80109
it('should detect UTF-8 BOM', async () => {
81110
const utf8Buffer = Buffer.from([
82111
0xEF, 0xBB, 0xBF, 0x48, 0x65, 0x6C, 0x6C, 0x6F

uploads/mime-bytes/src/file-type-detector.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,14 @@ export class FileTypeDetector {
2929
private extensionCache: Map<string, FileTypeDefinition[]>;
3030

3131
constructor(options: FileTypeDetectorOptions = {}) {
32-
// Create a copy of FILE_TYPES to avoid modifying the global registry
33-
this.fileTypes = [...FILE_TYPES];
32+
// Create a copy of FILE_TYPES sorted so that longer magic byte sequences
33+
// are checked before shorter ones. This ensures that specific formats
34+
// (e.g. HEIC with 8-byte signature "ftypheic") are matched before generic
35+
// container formats (e.g. MP4 with 4-byte signature "ftyp") that share
36+
// the same prefix.
37+
this.fileTypes = [...FILE_TYPES].sort(
38+
(a, b) => b.magicBytes.length - a.magicBytes.length
39+
);
3440
this.options = {
3541
peekBytes: options.peekBytes || 32,
3642
checkMultipleOffsets: options.checkMultipleOffsets !== false,

0 commit comments

Comments
 (0)