Optimización y compresión de imágenes mediante AJAX en el backend de FastAdmin

Para mejorar el rendimiento del servidor y reducir el consumo de almacenamiento en proyectos basados en FastAdmin, es fundamental procesar las imágenes durante el proceso de carga. Por defecto, el framework guarda los archivos con su peso original, pero podemos intervenir el controlador de subida para aplicar una compresión automática utilizando la librería GD de PHP.

El archivo encargado de gestionar estas operaciones es application/admin/controller/Ajax.php. Dentro de este controlador, debemos localizar el método upload() e insertar nuestra lógica de procesamiento inmediatamente después de la ejecución del hook que notifica la finalización de la subida.

Busque la siguienet línea de código en el método mencionado:

\think\Hook::listen("upload_after", $attachment);

A continuación, implemente el siguiente bloque de código para interceptar el archivo, verificar si es una imagen y reducir sus dimensiones o calidad en caso de exceder un tamaño específico:

// Definición de tipos MIME y extensiones permitidas para procesamiento
$formatosSoportados = ['image/gif', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/png', 'image/webp'];
$extArchivo = strtolower(pathinfo($attachment['url'], PATHINFO_EXTENSION));

if (in_array($attachment['mimetype'], $formatosSoportados) || in_array($extArchivo, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'webp'])) {
    $limitePeso = 1024 * 500; // Umbral de 500KB para activar la compresión
    
    if ($attachment['filesize'] > $limitePeso) {
        // Cálculo dinámico para evitar errores de memoria (Memory Limit)
        $memoriaEstimada = $imgInfo[0] * $imgInfo[1] * ($imgInfo['bits'] / 8) * 4;
        $ajusteMemoria = memory_get_usage() + $memoriaEstimada + 100000000;
        ini_set("memory_limit", $ajusteMemoria);

        $rutaAbsoluta = ROOT_PATH . 'public' . $attachment['url'];
        $procesadoExitoso = false;

        // Procesamiento específico para formatos JPEG
        if (preg_match('/jpg|jpeg/i', $attachment['mimetype'])) {
            $recursoOriginal = @imagecreatefromjpeg($rutaAbsoluta);
            if ($recursoOriginal) {
                $anchoFinal = $imgInfo[0] / 2;
                $altoFinal = $imgInfo[1] / 2;
                $lienzo = imagecreatetruecolor($anchoFinal, $altoFinal);
                
                imagecopyresampled($lienzo, $recursoOriginal, 0, 0, 0, 0, $anchoFinal, $altoFinal, $imgInfo[0], $imgInfo[1]);
                imagejpeg($lienzo, $rutaAbsoluta, 60); // Calidad ajustada al 60%
                $procesadoExitoso = true;
            }
        } 
        // Procesamiento específico para formatos PNG
        else if (preg_match('/png/i', $attachment['mimetype'])) {
            $recursoOriginal = @imagecreatefrompng($rutaAbsoluta);
            if ($recursoOriginal) {
                $anchoFinal = $imgInfo[0] / 2;
                $altoFinal = $imgInfo[1] / 2;
                $lienzo = imagecreatetruecolor($anchoFinal, $altoFinal);

                // Preservar la transparencia del PNG
                imagealphablending($lienzo, false);
                imagesavealpha($lienzo, true);
                
                imagecopyresampled($lienzo, $recursoOriginal, 0, 0, 0, 0, $anchoFinal, $altoFinal, $imgInfo[0], $imgInfo[1]);
                imagepng($lienzo, $rutaAbsoluta, 5); // Nivel de compresión de 1 a 9
                $procesadoExitoso = true;
            }
        }

        // Liberación de recursos de memoria
        if (isset($lienzo) && is_resource($lienzo)) {
            imagedestroy($lienzo);
        }
        if (isset($recursoOriginal) && is_resource($recursoOriginal)) {
            imagedestroy($recursoOriginal);
        }
    }
}

Consideraciones técnicas

  • Ajuste de memoria: La función ini_set("memory_limit", ...) es crucial al manipular imágenes de alta resolución (especialmente PNG), ya que la función imagecreatefrompng descomprime los datos en memoria RAM, lo que puede causar el agotamiento de la misma en entornos con límites estrictos.
  • Parámetros de salida: En la función imagejpeg, el tercer parámetro acepta valores de 0 a 100 (siendo 100 la máxima calidad). Para imagepng, el rango de compresión es de 0 a 9.
  • Escalado: En este ejemplo, se ha configurado para reducir las dimensiones a la mitad (/ 2), lo que reduce drásticamente el peso del archivo final además de la compresión por algoritmo.

Etiquetas: FastAdmin ThinkPHP PHP-GD Optimización-Web Compresión-Imágenes

Publicado el 7-12 19:54