filetype
import filetype from "filetype";filetype tells you a file’s media type, the Content-Type to send it
with: from its name ("photo.JPG" is "image/jpeg") or from its first
bytes, and the other way, the usual extension of a type. The table is built
into tape, not read from the operating system, so a program gets the same
answer on Windows, Linux and macOS, natively and in tape run. It comes
from mime-db, the table Node.js uses,
keeping the types registered with IANA or listed by the Apache web server.
filetype allocates nothing and touches nothing outside your program:
it works in every profile, t0 included, in pure modules and at compile
time. Every answer is a string that lives as long as the program. A program
using it carries the table, about 40 KB.
By file name
pub fn media_type(path: []const u8) -> ?[]const u8The media type for the file name’s extension, upper or lower case. Only
the last extension counts, and only the file name (after the last / or
\). null when there is no extension, for a dotfile such as .bashrc,
and for an extension the table doesn’t know; send those as
application/octet-stream.
filetype.media_type("photo.JPG") // "image/jpeg"
filetype.media_type("C:\\Users\\Ann\\notes.txt") // "text/plain"
filetype.media_type("backup.tar.gz") // "application/gzip"
filetype.media_type("report.docx") // "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
filetype.media_type("Makefile") // null
filetype.media_type(".bashrc") // null
fn content_type(name: []const u8) -> []const u8 {
return filetype.media_type(name) or { "application/octet-stream" };
}Attaching a file to an email with mime:
d.attach(name, filetype.media_type(name) or { "application/octet-stream" }, data);The usual extension of a type
pub fn extension(media: []const u8) -> ?[]const u8The extension files of that type usually have, without the dot. Upper or
lower case, and parameters such as ; charset=utf-8 are ignored, so a
Content-Type header can be passed as it is. null for a type the table
doesn’t know. Use it to name a file you received:
filetype.extension("image/jpeg") // "jpg"
filetype.extension("text/html; charset=UTF-8") // "html"
filetype.extension("application/x-unknown") // null
let ext: []const u8 = filetype.extension(content_type) or { "bin" };
let name: string = "download.{ext}";By content
pub fn sniff(data: []const u8) -> ?[]const u8The media type from the file’s first bytes, the way browsers recognise
files (the WHATWG MIME Sniffing Standard’s signatures), when the name is
missing or can’t be trusted. It knows images (PNG, JPEG, GIF, WebP, BMP,
ICO, TIFF, HEIC, AVIF, JPEG XL), audio and video (MP3, AAC in MP4/M4A,
Ogg, Opus, FLAC, WAV, AIFF, MIDI, MP4, QuickTime, 3GP, WebM, Matroska,
AVI), fonts (TTF, OTF, WOFF, WOFF2, EOT), archives (zip, gzip, RAR, 7z,
bzip2, xz), PDF and PostScript. A few hundred bytes are plenty; a short
buffer is fine, it never reads past the end. null when nothing matches,
and for text of any kind (HTML, XML, JSON, plain text): text has no
signature.
fn type_of(name: []const u8, data: []const u8) -> []const u8 {
let by_content: ?[]const u8 = filetype.sniff(data);
if (by_content != null) { return by_content!; }
return filetype.media_type(name) or { "application/octet-stream" };
}The answer is the same type media_type gives for that format’s usual
extension. Office documents, EPUB and Android packages are zip files
inside, and sniff as application/zip: their name is more precise.
Last modified: