12 de noviembre de 2012

Imagen corrupta desde un script PHP

Hace poco tiempo tuve el siguiente error en la descarga de una imagen desde un script PHP:
Error: Not a JPEG file: starts with 0x3c 0x21
Como el archivo era reconocido del tipo mime 'image/jpeg', entonces el error no se originaba en el envío de los Headers HTTP, sino que la data propiamente tal de la imagen se había corrompido.

Después de mucho investigar, encontré que el problema sucedía porque se agregaban algunos bytes del buffer de salida de PHP.
La solución al problema la aportaba TimB el 11 de febrero del 2008, en un post en la página:
http://us.php.net/readfile
 
La solución es agregar la instrucción ob_end_flush() justo antes de la llamada a la función readfile() de PHP.

Solución a la corrupción de la imagen

El código queda algo así:
<?php
....
header('Content-Type: image/jpeg');
header('Accept-Ranges: bytes');
header('Content-Length: ' . $file_size);
....
//justo antes de hacer la llamada a readfile()
ob_end_flush();
readfile($file);

También se puede usar alternativamente la función de php 'file_get_contents()', usando un 'echo'.
Tiene ventajas usar la función readfile(), pues en general no presenta problemas de memoria cuando las imágenes son muy grandes, a diferencia si usáramos alguna función perteneciente a la librería GD de PHP.