@tnnquang/file-type-detector
v1.0.0
Published
Detect real file type by analyzing magic bytes - secure and reliable
Maintainers
Readme
File Type Detector
Detect real file types by analyzing magic bytes (file signatures), not file extensions.
Perfect for: Upload validation, security checks, file processing pipelines.
Installation
npm install @tnnquang/file-type-detectorQuick Start
import { detectFileType } from "@tnnquang/file-type-detector";
// Node.js
const buffer = fs.readFileSync("image.jpg");
const result = await detectFileType(buffer);
// Browser
const file = event.target.files[0];
const result = await detectFileType(file);
console.log(result);
// {
// mimeType: 'image/jpeg',
// typeName: 'JPEG',
// extension: 'jpg',
// category: 'image',
// confidence: 'high',
// isValid: true,
// isSpoofed: false,
// magicBytes: 'FF D8 FF E0...'
// }API
detectFileType(input, options?)
Detect file type from buffer/blob/file.
const result = await detectFileType(file, {
bytesToRead: 65536, // Bytes to analyze (default: 64KB)
expectedExtension: "jpg", // For validation
expectedMimeType: "image/jpeg", // For validation
});Returns:
{
mimeType: string | null; // 'image/jpeg'
typeName: string; // 'JPEG'
extension: string | null; // 'jpg'
category: FileCategory; // 'image'
confidence: ConfidenceLevel; // 'high' | 'medium' | 'low' | 'none'
isValid: boolean; // Matches expected type?
isSpoofed: boolean; // Extension was faked?
magicBytes: string; // First 16 bytes in hex
}isFileType(input, mimeType)
Quick check for specific MIME type.
const isPNG = await isFileType(buffer, "image/png");isFileCategory(input, category)
Check by category.
const isImage = await isFileCategory(file, "image");validateWhitelist(input, allowedTypes)
Whitelist validation.
const result = await validateWhitelist(file, [
"image/jpeg",
"image/png",
"application/pdf",
]);
if (!result.isAllowed) {
throw new Error("File type not allowed");
}validateBlacklist(input, blockedTypes)
Blacklist validation.
const result = await validateBlacklist(file, [
"application/x-msdownload", // Block .exe
"application/x-executable", // Block Linux executables
]);Use Cases
Express.js Upload
import { validateWhitelist } from "@tnnquang/file-type-detector";
app.post("/upload", upload.single("file"), async (req, res) => {
const result = await validateWhitelist(req.file.buffer, [
"image/jpeg",
"image/png",
"application/pdf",
]);
if (!result.isAllowed || result.isSpoofed) {
return res.status(400).json({ error: "Invalid file" });
}
// Process file...
});React Component
const handleFile = async (e) => {
const file = e.target.files[0];
const result = await detectFileType(file);
if (result.isSpoofed) {
alert("File type mismatch detected!");
return;
}
if (result.category !== "image") {
alert("Only images allowed");
return;
}
// Upload file...
};Security Scanner
import { detectFileType } from "@tnnquang/file-type-detector";
async function scanFile(buffer, filename) {
const ext = filename.split(".").pop();
const result = await detectFileType(buffer, { expectedExtension: ext });
// Detect spoofed extensions
if (result.isSpoofed) {
console.warn(`${filename} is fake! Actually ${result.typeName}`);
}
// Block executables
if (result.category === "executable") {
console.error(`Executable detected: ${filename}`);
}
}Supported File Types (70+ formats)
Images (11 formats)
| Extension | MIME Type | Format Name |
| --------------- | --------------- | -------------- |
| .jpg, .jpeg | image/jpeg | JPEG |
| .png | image/png | PNG |
| .gif | image/gif | GIF (87a, 89a) |
| .webp | image/webp | WebP |
| .bmp | image/bmp | BMP |
| .tiff, .tif | image/tiff | TIFF (LE/BE) |
| .ico | image/x-icon | ICO |
| .svg | image/svg+xml | SVG |
| .heic | image/heic | HEIC |
| .heif | image/heif | HEIF |
| .avif | image/avif | AVIF |
Videos (6 formats)
| Extension | MIME Type | Format Name |
| --------- | ------------------ | --------------- |
| .mp4 | video/mp4 | MP4 |
| .avi | video/x-msvideo | AVI |
| .mkv | video/x-matroska | MKV |
| .webm | video/webm | WebM |
| .flv | video/x-flv | FLV |
| .mov | video/quicktime | MOV (QuickTime) |
🎵 Audio (6 formats)
| Extension | MIME Type | Format Name |
| --------- | ------------- | ----------- |
| .mp3 | audio/mpeg | MP3 (ID3) |
| .wav | audio/wav | WAV |
| .ogg | audio/ogg | OGG |
| .flac | audio/flac | FLAC |
| .aac | audio/aac | AAC |
| .m4a | audio/x-m4a | M4A |
Documents (7 formats)
| Extension | MIME Type | Format Name |
| --------- | --------------------------------------------------------------------------- | ------------------ |
| .pdf | application/pdf | PDF |
| .doc | application/msword | DOC (Word 97-2003) |
| .docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document | DOCX |
| .xlsx | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | XLSX (Excel) |
| .pptx | application/vnd.openxmlformats-officedocument.presentationml.presentation | PPTX (PowerPoint) |
| .rtf | application/rtf | RTF |
| .odt | application/vnd.oasis.opendocument.text | ODT (OpenDocument) |
Archives (6 formats)
| Extension | MIME Type | Format Name |
| --------- | ------------------------------ | ------------------ |
| .zip | application/zip | ZIP |
| .rar | application/x-rar-compressed | RAR (v1.5+, v5.0+) |
| .7z | application/x-7z-compressed | 7Z |
| .gz | application/gzip | GZIP |
| .bz2 | application/x-bzip2 | BZIP2 |
| .tar | application/x-tar | TAR |
Executables (4 formats)
| Extension | MIME Type | Format Name |
| -------------- | --------------------------- | ------------------------ |
| .exe, .dll | application/x-msdownload | EXE/DLL (Windows) |
| - | application/x-executable | ELF (Linux) |
| - | application/x-mach-binary | Mach-O (macOS 32/64-bit) |
| .jar | application/java-archive | JAR (Java) |
Fonts (4 formats)
| Extension | MIME Type | Format Name |
| --------- | ------------ | ----------- |
| .ttf | font/ttf | TTF |
| .otf | font/otf | OTF |
| .woff | font/woff | WOFF |
| .woff2 | font/woff2 | WOFF2 |
3D Models (3 formats)
| Extension | MIME Type | Format Name |
| --------- | ------------------- | ------------------ |
| .glb | model/gltf-binary | GLB |
| .obj | model/obj | OBJ |
| .stl | model/stl | STL (ASCII/Binary) |
Security Best Practices
DO
- Always validate on server-side
- Use whitelist (not blacklist)
- Check for spoofed extensions
- Limit file sizes
- Validate both extension and content
DON'T
- Trust file extensions alone
- Only validate client-side
- Use blacklist for dangerous files
- Skip validation for "trusted" users
Example: Complete Validation
import { detectFileType } from "@tnnquang/file-type-detector";
async function validateUpload(file: File) {
// 1. Check file size
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
if (file.size > MAX_SIZE) {
throw new Error("File too large");
}
// 2. Detect real file type
const result = await detectFileType(file, {
expectedExtension: file.name.split(".").pop(),
});
// 3. Check for spoofing
if (result.isSpoofed) {
throw new Error("File extension does not match content");
}
// 4. Whitelist validation
const allowedTypes = ["image/jpeg", "image/png", "application/pdf"];
if (!result.mimeType || !allowedTypes.includes(result.mimeType)) {
throw new Error("File type not allowed");
}
// 5. Category check
if (result.category === "executable") {
throw new Error("Executable files are blocked");
}
return result; // File is safe
}⚡ Performance
- Detection speed: < 5ms for most files
- Memory efficient: Only reads first 64KB by default
- Zero dependencies: No external packages
- Small bundle: ~15KB minified
🔧 TypeScript Support
Full TypeScript support with complete type definitions:
import type {
DetectionResult,
FileCategory,
ConfidenceLevel,
} from "@tnnquang/file-type-detector";
// Type-safe usage
const result: DetectionResult = await detectFileType(buffer);
const category: FileCategory = result.category; // 'image' | 'video' | ...More Examples
Batch Processing
async function validateMultipleFiles(files: File[]) {
const results = await Promise.all(files.map((file) => detectFileType(file)));
const invalid = results.filter((r) => r.isSpoofed || !r.isValid);
if (invalid.length > 0) {
console.warn("Invalid files detected:", invalid);
}
return results;
}Custom Validation Logic
async function customValidation(file: File) {
const result = await detectFileType(file);
// Custom rules
if (result.category === "image") {
if (file.size > 5 * 1024 * 1024) {
throw new Error("Images must be under 5MB");
}
}
if (result.category === "document") {
if (result.mimeType !== "application/pdf") {
throw new Error("Only PDF documents allowed");
}
}
return result;
}FAQ
Q: Does it work in the browser?
A: Yes! Works in both Node.js and all modern browsers.
Q: Can I detect files without extensions?
A: Yes, detection is based on magic bytes, not extensions.
Q: How accurate is the detection?
A: Very accurate. Uses official file signatures from format specifications.
Q: What about encrypted/compressed files?
A: Detects the container format (ZIP, RAR, etc.), not contents inside.
Q: Performance impact?
A: Minimal. Only reads first 64KB of file by default.
License
Proprietary Software - Copyright © 2025 Tra Ngoc Nhat Quang. All Rights Reserved.
This is commercial software. See LICENSE for terms.
Key restrictions:
- ❌ No reverse engineering
- ❌ No code extraction
- ❌ No redistribution
- ✅ Use in your applications
- ✅ Commercial use allowed
Support
- Email: [email protected]
- Issues: GitHub Issues
Made with 🔐 by Tran Ngoc Nhat Quang • Securing file uploads since 2025
