@@ -202,7 +202,167 @@ public static function base(string $path): string
202202 */
203203 public static function mimeType (string $ path ): string |false
204204 {
205- return mime_content_type ($ path );
205+ // Check if path is a URL
206+ $ isUrl = filter_var ($ path , FILTER_VALIDATE_URL );
207+
208+ [$ extension , $ mime ] = [
209+ pathinfo ($ path , PATHINFO_EXTENSION ),
210+ !$ isUrl && self ::isFile ($ path ) ? (@mime_content_type ($ path ) ?: false ) : false
211+ ];
212+
213+ // if mime is not found, try to guess it from the extension
214+ if ($ mime === false ) {
215+ $ mimes = [
216+ // ====== IMAGES ======
217+ 'jpg ' => 'image/jpeg ' ,
218+ 'jpeg ' => 'image/jpeg ' ,
219+ 'jpe ' => 'image/jpeg ' ,
220+ 'png ' => 'image/png ' ,
221+ 'gif ' => 'image/gif ' ,
222+ 'bmp ' => 'image/bmp ' ,
223+ 'webp ' => 'image/webp ' ,
224+ 'avif ' => 'image/avif ' ,
225+ 'heif ' => 'image/heif ' ,
226+ 'heic ' => 'image/heic ' ,
227+ 'svg ' => 'image/svg+xml ' ,
228+ 'svgz ' => 'image/svg+xml ' ,
229+ 'ico ' => 'image/x-icon ' ,
230+ 'cur ' => 'image/x-icon ' ,
231+ 'tif ' => 'image/tiff ' ,
232+ 'tiff ' => 'image/tiff ' ,
233+ 'psd ' => 'image/vnd.adobe.photoshop ' ,
234+ 'ai ' => 'application/postscript ' ,
235+ 'eps ' => 'application/postscript ' ,
236+ 'pdf ' => 'application/pdf ' ,
237+ 'apng ' => 'image/apng ' ,
238+ 'jxr ' => 'image/jxr ' ,
239+ 'wdp ' => 'image/vnd.ms-photo ' ,
240+ 'exr ' => 'image/x-exr ' ,
241+ 'hdr ' => 'image/vnd.radiance ' ,
242+
243+ // ====== DOCUMENTS ======
244+ 'txt ' => 'text/plain ' ,
245+ 'csv ' => 'text/csv ' ,
246+ 'tsv ' => 'text/tab-separated-values ' ,
247+ 'log ' => 'text/plain ' ,
248+ 'rtf ' => 'application/rtf ' ,
249+ 'doc ' => 'application/msword ' ,
250+ 'dot ' => 'application/msword ' ,
251+ 'docx ' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document ' ,
252+ 'dotx ' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template ' ,
253+ 'odt ' => 'application/vnd.oasis.opendocument.text ' ,
254+ 'ott ' => 'application/vnd.oasis.opendocument.text-template ' ,
255+ 'xls ' => 'application/vnd.ms-excel ' ,
256+ 'xlt ' => 'application/vnd.ms-excel ' ,
257+ 'xlsx ' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet ' ,
258+ 'xltx ' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template ' ,
259+ 'ods ' => 'application/vnd.oasis.opendocument.spreadsheet ' ,
260+ 'odp ' => 'application/vnd.oasis.opendocument.presentation ' ,
261+ 'ppt ' => 'application/vnd.ms-powerpoint ' ,
262+ 'pptx ' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation ' ,
263+ 'ppsx ' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow ' ,
264+ 'potx ' => 'application/vnd.openxmlformats-officedocument.presentationml.template ' ,
265+ 'xml ' => 'application/xml ' ,
266+ 'html ' => 'text/html ' ,
267+ 'htm ' => 'text/html ' ,
268+ 'json ' => 'application/json ' ,
269+ 'yaml ' => 'application/x-yaml ' ,
270+ 'yml ' => 'application/x-yaml ' ,
271+ 'md ' => 'text/markdown ' ,
272+
273+ // ====== ARCHIVES ======
274+ 'zip ' => 'application/zip ' ,
275+ 'rar ' => 'application/x-rar-compressed ' ,
276+ 'tar ' => 'application/x-tar ' ,
277+ 'gz ' => 'application/gzip ' ,
278+ 'tgz ' => 'application/gzip ' ,
279+ 'bz2 ' => 'application/x-bzip2 ' ,
280+ '7z ' => 'application/x-7z-compressed ' ,
281+ 'xz ' => 'application/x-xz ' ,
282+ 'iso ' => 'application/x-iso9660-image ' ,
283+
284+ // ====== AUDIO ======
285+ 'mp3 ' => 'audio/mpeg ' ,
286+ 'wav ' => 'audio/wav ' ,
287+ 'ogg ' => 'audio/ogg ' ,
288+ 'oga ' => 'audio/ogg ' ,
289+ 'flac ' => 'audio/flac ' ,
290+ 'aac ' => 'audio/aac ' ,
291+ 'm4a ' => 'audio/mp4 ' ,
292+ 'opus ' => 'audio/opus ' ,
293+ 'mid ' => 'audio/midi ' ,
294+ 'midi ' => 'audio/midi ' ,
295+
296+ // ====== VIDEO ======
297+ 'mp4 ' => 'video/mp4 ' ,
298+ 'm4v ' => 'video/x-m4v ' ,
299+ 'mov ' => 'video/quicktime ' ,
300+ 'wmv ' => 'video/x-ms-wmv ' ,
301+ 'avi ' => 'video/x-msvideo ' ,
302+ 'flv ' => 'video/x-flv ' ,
303+ 'webm ' => 'video/webm ' ,
304+ 'mkv ' => 'video/x-matroska ' ,
305+ '3gp ' => 'video/3gpp ' ,
306+ '3g2 ' => 'video/3gpp2 ' ,
307+
308+ // ====== CODE / WEB ======
309+ 'php ' => 'application/x-httpd-php ' ,
310+ 'js ' => 'application/javascript ' ,
311+ 'mjs ' => 'application/javascript ' ,
312+ 'jsx ' => 'text/jsx ' ,
313+ 'ts ' => 'application/typescript ' ,
314+ 'tsx ' => 'text/tsx ' ,
315+ 'css ' => 'text/css ' ,
316+ 'scss ' => 'text/x-scss ' ,
317+ 'less ' => 'text/x-less ' ,
318+ 'csv ' => 'text/csv ' ,
319+ 'conf ' => 'text/plain ' ,
320+ 'ini ' => 'text/plain ' ,
321+ 'env ' => 'text/plain ' ,
322+
323+ // ====== FONTS ======
324+ 'woff ' => 'font/woff ' ,
325+ 'woff2 ' => 'font/woff2 ' ,
326+ 'ttf ' => 'font/ttf ' ,
327+ 'otf ' => 'font/otf ' ,
328+ 'eot ' => 'application/vnd.ms-fontobject ' ,
329+
330+ // ====== EXECUTABLES / BINARIES ======
331+ 'exe ' => 'application/x-msdownload ' ,
332+ 'dll ' => 'application/x-msdownload ' ,
333+ 'bin ' => 'application/octet-stream ' ,
334+ 'dat ' => 'application/octet-stream ' ,
335+ 'msi ' => 'application/x-msi ' ,
336+ 'apk ' => 'application/vnd.android.package-archive ' ,
337+ 'deb ' => 'application/vnd.debian.binary-package ' ,
338+ 'rpm ' => 'application/x-rpm ' ,
339+ 'dmg ' => 'application/x-apple-diskimage ' ,
340+
341+ // ====== TEXT / SCRIPTING ======
342+ 'sh ' => 'application/x-sh ' ,
343+ 'bat ' => 'application/x-msdos-program ' ,
344+ 'cmd ' => 'application/cmd ' ,
345+ 'py ' => 'text/x-python ' ,
346+ 'rb ' => 'text/x-ruby ' ,
347+ 'go ' => 'text/x-go ' ,
348+ 'java ' => 'text/x-java-source ' ,
349+ 'c ' => 'text/x-c ' ,
350+ 'cpp ' => 'text/x-c++ ' ,
351+ 'h ' => 'text/x-c ' ,
352+ 'cs ' => 'text/x-csharp ' ,
353+
354+ // ====== OTHER ======
355+ 'bak ' => 'application/octet-stream ' ,
356+ 'lock ' => 'text/plain ' ,
357+ 'sql ' => 'application/sql ' ,
358+ 'db ' => 'application/x-sqlite3 ' ,
359+ 'sqlite ' => 'application/x-sqlite3 ' ,
360+ ];
361+
362+ $ mime = $ mimes [$ extension ] ?? false ;
363+ }
364+
365+ return $ mime ;
206366 }
207367
208368 /**
0 commit comments