49 lines
2.0 KiB
JavaScript
49 lines
2.0 KiB
JavaScript
'use strict';
|
|
const path = require('path');
|
|
|
|
// Types a browser can show inline. The type is derived from the file name on the
|
|
// server, the type the client claimed at upload time is never trusted.
|
|
// Text is always served as text/plain, html is deliberately not listed.
|
|
const MEDIA = {
|
|
png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif',
|
|
webp: 'image/webp', avif: 'image/avif', bmp: 'image/bmp', svg: 'image/svg+xml',
|
|
pdf: 'application/pdf',
|
|
mp4: 'video/mp4', m4v: 'video/mp4', mov: 'video/quicktime', webm: 'video/webm', ogv: 'video/ogg',
|
|
mp3: 'audio/mpeg', wav: 'audio/wav', ogg: 'audio/ogg', m4a: 'audio/mp4', flac: 'audio/flac',
|
|
};
|
|
|
|
const TEXT = ['txt', 'md', 'log', 'json', 'xml', 'csv', 'tsv', 'yml', 'yaml', 'ini', 'conf', 'cfg',
|
|
'js', 'mjs', 'ts', 'jsx', 'tsx', 'vue', 'css', 'scss', 'less', 'sh', 'bat', 'cmd', 'ps1', 'py',
|
|
'java', 'c', 'h', 'cpp', 'hpp', 'cs', 'php', 'sql', 'lua', 'pug', 'go', 'rs', 'rb'];
|
|
|
|
const PREVIEW = { ...MEDIA };
|
|
TEXT.forEach(ext => { PREVIEW[ext] = 'text/plain; charset=utf-8'; });
|
|
|
|
function extname(name) {
|
|
return path.extname(String(name || '')).slice(1).toLowerCase();
|
|
}
|
|
|
|
/** Content-Type for inline preview or null when the file has to be downloaded. */
|
|
function previewMime(name) {
|
|
return PREVIEW[extname(name)] || null;
|
|
}
|
|
|
|
/** 'image' | 'pdf' | 'video' | 'audio' | 'text' | null */
|
|
function previewKind(name) {
|
|
const mime = previewMime(name);
|
|
if (!mime) return null;
|
|
if (mime === 'application/pdf') return 'pdf';
|
|
return mime.split('/')[0];
|
|
}
|
|
|
|
/** Detect the image type of a thumbnail by its signature. */
|
|
function sniffImage(buf) {
|
|
if (!Buffer.isBuffer(buf) || buf.length < 12) return null;
|
|
if (buf.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))) return 'image/png';
|
|
if (buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff) return 'image/jpeg';
|
|
if (buf.subarray(0, 4).toString('latin1') === 'RIFF' && buf.subarray(8, 12).toString('latin1') === 'WEBP') return 'image/webp';
|
|
return null;
|
|
}
|
|
|
|
module.exports = { previewMime, previewKind, sniffImage };
|