diff --git a/api/lab/descargar_orden.php b/api/lab/descargar_orden.php index d166b51..5270c6a 100644 --- a/api/lab/descargar_orden.php +++ b/api/lab/descargar_orden.php @@ -46,12 +46,38 @@ if (!$path || !$base || strpos($path, $base) !== 0 || !is_file($path)) { exit; } -// Detectar MIME real -$finfo = finfo_open(FILEINFO_MIME_TYPE); -$mime = finfo_file($finfo, $path); -finfo_close($finfo); +// Detectar MIME real — 3 capas para máxima fiabilidad con archivos .bin -// Mapa de extensiones como fallback +// Capa 1: finfo (usa magic bytes internamente) +$mime = ''; +if (function_exists('finfo_open')) { + $fi = finfo_open(FILEINFO_MIME_TYPE); + $mime = $fi ? (string)finfo_file($fi, $path) : ''; + if ($fi) finfo_close($fi); +} + +// Capa 2: Lectura manual de magic bytes (funciona aunque finfo falle o devuelva octet-stream) +if (!$mime || $mime === 'application/octet-stream') { + $handle = fopen($path, 'rb'); + $bytes = $handle ? fread($handle, 12) : ''; + if ($handle) fclose($handle); + + if (substr($bytes, 0, 3) === "\xFF\xD8\xFF") { + $mime = 'image/jpeg'; + } elseif (substr($bytes, 0, 8) === "\x89PNG\r\n\x1a\n") { + $mime = 'image/png'; + } elseif (substr($bytes, 0, 5) === '%PDF-') { + $mime = 'application/pdf'; + } elseif (substr($bytes, 0, 6) === 'GIF89a' || substr($bytes, 0, 6) === 'GIF87a') { + $mime = 'image/gif'; + } elseif (substr($bytes, 0, 4) === 'RIFF' && substr($bytes, 8, 4) === 'WEBP') { + $mime = 'image/webp'; + } elseif (substr($bytes, 0, 2) === 'PK') { + $mime = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; + } +} + +// Capa 3: Fallback por extensión declarada $ext = strtolower(pathinfo($fileParam, PATHINFO_EXTENSION)); $mimeMap = [ 'pdf' => 'application/pdf',