Last active
July 7, 2024 22:47
-
-
Save fmagrosoto/723d7a5acec719ad7705ac730be4abb2 to your computer and use it in GitHub Desktop.
Clase especial de PHP para poder subir un archivo al servidor y poder validar varias cosas, como el peso y el tipo MIME
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* CLASE PARA SUBIR UN ARCHIVO A LA CARPETA PASADA COMO PARÁMETRO | |
* | |
* Hay casos donde deberemos de estar subiendo archivos al servidor. Antes de subirlos, | |
* deberemos de estar validando el peso y el formato. Y una vez subido el archivo, deberemos | |
* de regresar el nombre del archivo, debidamente limpiado y con una marca de tiempo para | |
* evitar que haya duplicados y se sobreescriban. Será entonces cuando podamos almacenar | |
* en una base de datos el nombre del archivo. | |
* | |
* @author Fernando Magrosoto V. | |
* @since v1.0.0 | |
* @license MIT | |
* @package helpers | |
*/ | |
namespace helpers; | |
use Exception; | |
use Web; | |
class SubirArchivoHelper | |
{ | |
/** | |
* CARGAR EL ARCHIVO | |
* | |
* Se deberá de llamar a este método siempre y cuando se haya validado que no haya un campo vacío | |
* de archivo. Y de preferencia, antes de cualquier cosa, para evitar que se guarde un registro | |
* con el archivo vacío. Pero si el campo el opcional, entonces deberás de pensar en el mejor | |
* momento para llamar a este método. Vas a necesitar los siguientes parámetros. | |
* | |
* @internal Recuerda usar enctype multipart/form-data en el formulario, para permitir subir archivos | |
* @param string $campo Nombre del campo del formulario del archivo | |
* @param string $elPath La ruta donde se irá a almacenar el archivo, sin slashes ni al inicio ni al final | |
* @param int $peso El peso máximo permitido en bytes, ej. 2MB = (1024 * 1024 * 2) | |
* @param array $tiposPermitidos Los MIME de los tipos permitidos en un array, ej: ['application/pdf', 'image/png'] | |
* @return string El nombre del archivo limpio y acortado | |
* @throws Exception | |
*/ | |
public static function cargarArchivo(string $campo, string $elPath, int $peso, array $tiposPermitidos): string | |
{ | |
$web = Web::instance(); | |
// Validar que no pese más del peso solicitado | |
if ($_FILES[$campo]['size'] > $peso) { | |
throw new Exception('El archivo pesa más de lo solicitado.'); | |
} | |
// Validar que el archivo sea un PDF | |
$tipoArchivo = mime_content_type($_FILES[$campo]['tmp_name']); | |
if (!in_array($tipoArchivo, $tiposPermitidos)) { | |
throw new Exception('El archivo no tiene el formato solicitado.'); | |
} | |
// Luego, limpiar el nombre del archivo. Le vamos a quitar espacios, acentos, caracteres especiales y | |
// vamos a pasar a minúsculas el nombre completo, incluyendo la extensión. | |
// Uso SLUG para limpiar la cadena de texto, que es parte de Fat Free Framework, pero se puede usar | |
// cualquier otro método. | |
$extension = $web->slug(pathinfo($_FILES[$campo]['name'], PATHINFO_EXTENSION)); | |
$nombreSinExtension = $web->slug(str_replace( | |
$extension, | |
'', | |
pathinfo($_FILES[$campo]['name'], PATHINFO_BASENAME) | |
)); | |
// Y vamos a hacer que el nombre no mida más de 35 caracteres | |
if (strlen($nombreSinExtension) > 35) { | |
$nombreSinExtension = substr($nombreSinExtension, 0, 35); | |
} | |
// Armamos el nombre completo (limpio y acortado) | |
// OJO, el campo usado para el nombre del archivo en la BD es VARCHAR(50) | |
// Entonces, 35 caracteres del nombre del archivo, más 5 caracteres del mini token, porque | |
// no quiero que haya duplicados, más 4 ó 5 caracteres de la extensión | |
// (incluyendo el punto) = 50 caracteres máximo (hasta sobran). | |
$nombreArchivo = mt_rand(10000, 19999) . '-' . $nombreSinExtension . '.' . $extension; | |
// Y lo grabamos | |
if (!is_dir($elPath)) { | |
mkdir($elPath, 0777, true); | |
} | |
if (move_uploaded_file($_FILES[$campo]['tmp_name'], $elPath . '/' . $nombreArchivo) === false) { | |
throw new Exception(); | |
} | |
// Retornamos el nombre completo del archivo | |
return $nombreArchivo; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment