Tipos MIME
MIME (Multipurpose Internet Mail Extensions) es un estándar que indica la naturaleza y el formato de un documento, archivo o conjunto de datos. Originalmente diseñado para el correo electrónico, ahora se utiliza ampliamente en protocolos web para identificar el tipo de contenido que se está transmitiendo.
Un tipo MIME tiene la siguiente estructura:
tipo/subtipo
Por ejemplo: image/jpeg, application/pdf, text/html
Importancia en la subida de archivos
Cuando un usuario sube un archivo, el navegador envía el tipo MIME del archivo en el campo $_FILES['archivo']['type']. Sin embargo, este valor no es confiable desde el punto de vista de la seguridad, ya que puede ser manipulado fácilmente por un atacante.
Validación correcta del tipo MIME
Para verificar realmente el tipo de archivo, PHP ofrece la función finfo_file():
<?php
// Método NO seguro (puede ser falsificado)
$tipoReportado = $_FILES['archivo']['type'];
// Método SEGURO (analiza el contenido real del archivo)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$tipoReal = finfo_file($finfo, $_FILES['archivo']['tmp_name']);
finfo_close($finfo);
echo "Tipo reportado: " . $tipoReportado . "\n";
echo "Tipo real: " . $tipoReal . "\n";
// Validar contra una lista blanca
$tiposPermitidos = ['image/jpeg', 'image/png', 'application/pdf'];
if (!in_array($tipoReal, $tiposPermitidos)) {
die("Tipo de archivo no permitido");
}
?>
Tipos MIME más comunes
Imágenes
| Tipo MIME | Extensión | Descripción |
|---|---|---|
image/jpeg | .jpg, .jpeg | Imagen JPEG |
image/png | .png | Imagen PNG con soporte de transparencia |
image/gif | .gif | Imagen GIF, soporta animación |
image/webp | .webp | Formato moderno de imagen optimizado |
image/svg+xml | .svg | Gráfico vectorial escalable |
image/bmp | .bmp | Imagen bitmap de Windows |
image/tiff | .tif, .tiff | Formato de imagen de alta calidad |
image/x-icon | .ico | Icono (favicon) |
Documentos
| Tipo MIME | Extensión | Descripción |
|---|---|---|
application/pdf | .pdf | Documento PDF |
application/msword | .doc | Documento de Word (versión antigua) |
application/vnd.openxmlformats-officedocument.wordprocessingml.document | .docx | Documento de Word (formato moderno) |
application/vnd.ms-excel | .xls | Hoja de cálculo Excel (versión antigua) |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | .xlsx | Hoja de cálculo Excel (formato moderno) |
application/vnd.ms-powerpoint | .ppt | Presentación PowerPoint (versión antigua) |
application/vnd.openxmlformats-officedocument.presentationml.presentation | .pptx | Presentación PowerPoint (formato moderno) |
application/vnd.oasis.opendocument.text | .odt | Documento de texto OpenDocument |
application/vnd.oasis.opendocument.spreadsheet | .ods | Hoja de cálculo OpenDocument |
text/plain | .txt | Archivo de texto plano |
text/csv | .csv | Valores separados por comas |
application/rtf | .rtf | Formato de texto enriquecido |
Audio
| Tipo MIME | Extensión | Descripción |
|---|---|---|
audio/mpeg | .mp3 | Audio MP3 |
audio/wav | .wav | Audio WAV sin comprimir |
audio/ogg | .ogg | Audio Ogg Vorbis |
audio/webm | .weba | Audio WebM |
audio/aac | .aac | Advanced Audio Coding |
audio/flac | .flac | Audio sin pérdida FLAC |
audio/midi | .mid, .midi | Audio MIDI |
Vídeo
| Tipo MIME | Extensión | Descripción |
|---|---|---|
video/mp4 | .mp4 | Vídeo MP4 (H.264) |
video/mpeg | .mpeg, .mpg | Vídeo MPEG |
video/webm | .webm | Vídeo WebM |
video/ogg | .ogv | Vídeo Ogg |
video/x-msvideo | .avi | Vídeo AVI |
video/quicktime | .mov | Vídeo QuickTime |
video/x-matroska | .mkv | Vídeo Matroska |
Archivos comprimidos
| Tipo MIME | Extensión | Descripción |
|---|---|---|
application/zip | .zip | Archivo ZIP |
application/x-rar-compressed | .rar | Archivo RAR |
application/x-7z-compressed | .7z | Archivo 7-Zip |
application/x-tar | .tar | Archivo TAR |
application/gzip | .gz | Archivo GZIP |
Código y texto
| Tipo MIME | Extensión | Descripción |
|---|---|---|
text/html | .html, .htm | Documento HTML |
text/css | .css | Hoja de estilos CSS |
text/javascript | .js | Código JavaScript |
application/json | .json | Datos JSON |
application/xml | .xml | Documento XML |
text/xml | .xml | Documento XML (alternativo) |
application/x-php | .php | Script PHP |
text/x-python | .py | Script Python |
Otros formatos comunes
| Tipo MIME | Extensión | Descripción |
|---|---|---|
application/octet-stream | * | Datos binarios genéricos (sin tipo específico) |
font/woff | .woff | Fuente web WOFF |
font/woff2 | .woff2 | Fuente web WOFF2 |
font/ttf | .ttf | Fuente TrueType |
application/x-font-otf | .otf | Fuente OpenType |
Ejemplo completo de validación por categoría
<?php
function validarArchivoPorCategoria($archivo, $categoria) {
// Obtener el tipo MIME real
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$tipoMime = finfo_file($finfo, $archivo['tmp_name']);
finfo_close($finfo);
// Definir tipos permitidos por categoría
$categorias = [
'imagen' => [
'image/jpeg',
'image/png',
'image/gif',
'image/webp'
],
'documento' => [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'text/plain'
],
'audio' => [
'audio/mpeg',
'audio/wav',
'audio/ogg',
'audio/webm'
],
'video' => [
'video/mp4',
'video/webm',
'video/ogg'
],
'comprimido' => [
'application/zip',
'application/x-rar-compressed',
'application/x-7z-compressed'
]
];
// Verificar si la categoría existe
if (!isset($categorias[$categoria])) {
return [
'valido' => false,
'mensaje' => 'Categoría no reconocida'
];
}
// Validar el tipo MIME
if (in_array($tipoMime, $categorias[$categoria])) {
return [
'valido' => true,
'tipo' => $tipoMime,
'mensaje' => 'Archivo válido'
];
} else {
return [
'valido' => false,
'tipo' => $tipoMime,
'mensaje' => "Tipo de archivo no permitido para la categoría '{$categoria}'"
];
}
}
// Uso
if (isset($_FILES['archivo']) && $_FILES['archivo']['error'] === UPLOAD_ERR_OK) {
$resultado = validarArchivoPorCategoria($_FILES['archivo'], 'imagen');
if ($resultado['valido']) {
echo "Archivo válido: " . $resultado['tipo'];
// Proceder con la subida
} else {
echo "Error: " . $resultado['mensaje'];
if (isset($resultado['tipo'])) {
echo " (Tipo detectado: " . $resultado['tipo'] . ")";
}
}
}
?>
Validación avanzada: combinando MIME y extensión
Para una seguridad óptima, se recomienda validar tanto el tipo MIME como la extensión del archivo:
<?php
function validarArchivoCompleto($archivo) {
// Tipos MIME y extensiones permitidas
$tiposPermitidos = [
'image/jpeg' => ['jpg', 'jpeg'],
'image/png' => ['png'],
'image/gif' => ['gif'],
'application/pdf' => ['pdf'],
'application/msword' => ['doc'],
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx']
];
// Obtener tipo MIME real
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$tipoMime = finfo_file($finfo, $archivo['tmp_name']);
finfo_close($finfo);
// Obtener extensión
$extension = strtolower(pathinfo($archivo['name'], PATHINFO_EXTENSION));
// Validar que el tipo MIME esté permitido
if (!array_key_exists($tipoMime, $tiposPermitidos)) {
return [
'valido' => false,
'mensaje' => 'Tipo de archivo no permitido'
];
}
// Validar que la extensión coincida con el tipo MIME
if (!in_array($extension, $tiposPermitidos[$tipoMime])) {
return [
'valido' => false,
'mensaje' => 'La extensión del archivo no coincide con su contenido real'
];
}
return [
'valido' => true,
'tipo' => $tipoMime,
'extension' => $extension
];
}
// Ejemplo de uso
if (isset($_FILES['archivo']) && $_FILES['archivo']['error'] === UPLOAD_ERR_OK) {
$validacion = validarArchivoCompleto($_FILES['archivo']);
if ($validacion['valido']) {
echo "Archivo válido: {$validacion['tipo']} (.{$validacion['extension']})";
// Continuar con el procesamiento
} else {
die("Error: " . $validacion['mensaje']);
}
}
?>
Consideraciones especiales
application/octet-stream
Este tipo MIME genérico se utiliza cuando el servidor no puede determinar el tipo específico del archivo. Es conveniente rechazar archivos con este tipo MIME en aplicaciones que requieren alta seguridad.
Archivos peligrosos
Algunos tipos MIME deben ser bloqueados por razones de seguridad:
application/x-php: Archivos PHP ejecutablesapplication/x-httpd-php: Scripts PHPapplication/x-sh: Scripts de shellapplication/x-executable: Ejecutables
<?php
// Lista negra de tipos peligrosos
$tiposPeligrosos = [
'application/x-php',
'application/x-httpd-php',
'application/x-sh',
'application/x-executable',
'application/x-msdownload',
'text/x-php'
];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$tipoMime = finfo_file($finfo, $_FILES['archivo']['tmp_name']);
finfo_close($finfo);
if (in_array($tipoMime, $tiposPeligrosos)) {
die("Este tipo de archivo está prohibido por razones de seguridad");
}
?>
Validar el tipo con finfo_file()
La validación correcta de tipos MIME es fundamental para la seguridad de cualquier aplicación que permita subida de archivos. Nunca confíes únicamente en la extensión del archivo o en el tipo MIME reportado por el navegador. Utiliza siempre funciones como finfo_file() para analizar el contenido real del archivo y valida contra una lista blanca de tipos permitidos específicos para tu aplicación.